Previous Tip  |  Next Tip  |  Design Tips   | [Bill's Home]

216. Client/server connections in .NET

[Run program] ... run the server first, and then the client connecting to the IP address of the server...

.NET is an amazing environment, and it is simple to create client/server connections. The key thing is that socket connections are blocking, which would cause the program to freeze whenever a connection is made from a client to the server. It would only unfreeze when the connection had been made. This might be okay if the connection is fairly quick, but it would be unacceptable if there was a long delay, or if the server was not connection. Also when data is to be received, it would also block. The answer to this is Asynchronous sockets, where a callback method, where a connection request is made, and a callback method is used to complete the connection.

This above program [Programs] has two programs. The first is a server which should be run first either on the local machine or on a remote host:

By default the server will listen on port 1001 (but this can be changed to other ports, as required. The client has the form:

The server listens for a connection, and the client connect to the server using the IP address of the server.

In Visual Studio, a client can be created with:

and the server with:

When the server is started, it will automatically start the server with:

private void Form1_Load(object sender, System.EventArgs e)
{
createServer();
toolTip1.SetToolTip(this.tbPortServer,"Please type in the port you require...");

}

which calls:

public void createServer()
{
try
{
serverSocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );

IPHostEntry ip = Dns.Resolve("");
int port = Convert.ToInt32(tbPortServer.Text);
tbIPserver.ReadOnly=false;

tbIPserver.Text=ip.AddressList[0].ToString();
tbIPserver.ReadOnly=true;

IPEndPoint iend = new IPEndPoint(ip.AddressList[0],port);
serverSocket.Bind(iend);

serverSocket.Listen(10);

serverSocket.BeginAccept( new AsyncCallback(AcceptCallback),serverSocket );
tbStatus.ReadOnly=false;

tbStatus.Text="Listening on Port: "+tbPortServer.Text;
tbStatus.ReadOnly=true;

tbTransmit.Focus();
}
catch {} ;

}

The BeginAccept() method is the key one here, and is used to define the call back method (AcceptCallback), which will be called when the connection is accept. Then when a connection is received it calls the following callback:

public void AcceptCallback(IAsyncResult ar)
{

try
{
Socket s = (Socket) ar.AsyncState;
serverSocket = s.EndAccept(ar);

tbStatus.ReadOnly=false;
tbStatus.Text="Connected ...";
tbStatus.ReadOnly=true;

string str = serverSocket.RemoteEndPoint.ToString();
string [] st = str.Split(':');
tbClientIP.ReadOnly=false;
tbClientPort.ReadOnly=false;

tbClientIP.Text=st[0];
tbClientPort.Text=st[1];

tbClientIP.ReadOnly=true;
tbClientPort.ReadOnly=true;

startReceive();
}
catch {} ;
}

On the client the event on the Connect button is then:

private void button1_Click(object sender, System.EventArgs e)
{
string ip = tbClientIP.Text;
int port = Convert.ToInt32(tbClientPort.Text);
add[0]=genip(ip,port);
test(add[0]);
textBox1.Text="Connecting...";
button2.Visible=true;
button3.Visible=true;
comboBox1.Visible=true;
}

which calls:

public void ConnectCallback(IAsyncResult asyn)
{
Socket s = (Socket)asyn.AsyncState ;

try
{
s.EndConnect( asyn );
s.GetType();
startReceive();
textBox1.Text="Connected...";
EndPoint r = s.RemoteEndPoint;
string str = r.ToString();
string [] strDetails = str.Split(':');
tbServerIP.Text= strDetails[0];
tbServerPort.Text=strDetails[1];
} catch {} ;
groupBox3.Visible=true;

}

public void startReceive()
{
AsyncCallback recieveData = new AsyncCallback( OnReceivedData );
m_clientSocket.BeginReceive( m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, m_clientSocket );
}
void test(IPEndPoint a )
{
try
{
m_clientSocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );

handle[0]=m_clientSocket.Handle;

m_clientSocket.BeginConnect(a, new AsyncCallback(ConnectCallback),m_clientSocket);

}
catch {} ;
}

If you want the solution file. ... please email me w.buchanan (at) napier.ac.uk, or fill in the form below...