Writing a TCP Client




Writing a TCP Client

Problem

You want to interact with a TCP-based server.

Solution

Use the MyTcpClient class shown in Figure to connect to and converse with a TCP-based server by passing the address and port of the server to talk to, using the System.Net.TcpClient class. This example will talk to the server from Recipe 16.1.

MyTcpClient class

class MyTcpClient
{

    private TcpClient _client = null;
    private IPAddress _address;
    private int _port;
    private IPEndPoint _endPoint = null;

    public MyTcpClient(IPAddress address, int port)
    {
        _address = address;
        _port = port;
        _endPoint = new IPEndPoint(_address, _port);
    }


    public void ConnectToServer(string msg)
    {
        try
        {
            _client = new TcpClient();
            _client.Connect(_endPoint);

            // Get the bytes to send for the message
            byte[] bytes = Encoding.ASCII.GetBytes(msg);
            // Get the stream to talk to the server on
            using (NetworkStream ns = _client.GetStream())
            {
                // Send message
                Trace.WriteLine("Sending message to server: " + msg);
                ns.Write(bytes, 0, bytes.Length);
                // Get the response
                // Buffer to store the response bytes
                bytes = new byte[1024];

                // Display the response
                int bytesRead = ns.Read(bytes, 0, bytes.Length);
                string serverResponse = Encoding.ASCII.GetString(bytes, 0, bytesRead);
                Trace.WriteLine("Server said: " + serverResponse);
            }
        }
        catch (SocketException se)
        {
            Trace.WriteLine("There was an error talking to the server: " +
                se.ToString());
        }
        finally
        {
            // Close everything
            if(_client != null) 
                _client.Close();
        }
    }
}

To use the MyTcpClient in a program, you can simply create an instance of it and call ConnectToServer to send a request. In this program, you first make three calls to the server to test the basic mechanism. Next, you enter a loop to really pound on it and make sure you force it over the default ThreadPool limit. This verifies that the server's mechanism for handling multiple requests is sound.

	static void Main(string[] args)
	{

	    MakeClientCallToServer("Just wanted to say hi");
	    MakeClientCallToServer("Just wanted to say hi again");
	    MakeClientCallToServer("Are you ignoring me?");

	    // Now send a bunch of messages…
	    string msg;
	    for (int i = 0; i < 100; i++)
	    {
	        msg = string.Format("I'll not be ignored! (round {0})", i); 
	        ThreadPool.QueueUserWorkItem(new WaitCallback(MakeClientCallToServer), msg);
	    }

	    Console.WriteLine("\n Press any key to continue… (if you can find it…)");
	    Console.Read(); 
	}

	static void MakeClientCallToServer(object objMsg)
	{
	    string msg = (string)objMsg;
	    MyTcpClient client = new MyTcpClient(IPAddress.Loopback,55555);
	    client.ConnectToServer(msg);
	}

The output on the client side for this exchange of messages is:

	Sending message to server: Just wanted to say hi
	Server said: Thanks call again!
	Sending message to server: Just wanted to say hi again
	Server said: Thanks call again!
	Sending message to server: Are you ignoring me?
	Server said: Thanks call again!
	 Press any key to continue… (if you can find it…)
	Sending message to server: I'll not be ignored! (round 0)
	Sending message to server: I'll not be ignored! (round 1)
	Server said: Thanks call again!
	Server said: Thanks call again!
	Sending message to server: I'll not be ignored! (round 2)
	Server said: Thanks call again!
	Sending message to server: I'll not be ignored! (round 3)
	Sending message to server: I'll not be ignored! (round 4)
	Server said: Thanks call again!
	Server said: Thanks call again!
	Sending message to server: I'll not be ignored! (round 5)
	Sending message to server: I'll not be ignored! (round 6)
	Server said: Thanks call again!
	Server said: Thanks call again!
	Sending message to server: I'll not be ignored! (round 7)
	Sending message to server: I'll not be ignored! (round 8)
	Server said: Thanks call again!
	[more output follows…]

Discussion

MyTcpClient.ConnectToServer is designed to send one message, get the response, display it as a string, then close the connection. To accomplish this, it creates a System.Net.TcpClient and connects to the server by calling the TcpClient.Connect method. Connect targets the server using an IPEndPoint built from the address and port that you passed to the MyTcpClient constructor.

MyTcpClient.ConnectToServer then gets the bytes for the string using the Encoding.ASCII.GetBytes method. Once it has the bytes to send, it gets the NetworkStream from the underlying System.Net.TcpClient by calling its GetStream method, then sends the message using the TcpClient.Write method.

In order to receive the response from the server, the blocking TcpClient.Read method is called. Once Read returns, the bytes are decoded to get the string that contains the response from the server. The connections are then closed and the client ends.

See Also

See the "TcpClient Class," "NetworkStream Class," and "Encoding.ASCII Property" topics in the MSDN documentation.