C# Socket Helper Classes





C# Socket Helper Classes

The .NET Framework supports the normal socket interface for advanced network programmers, but it also provides a simplified interface for easier network programming. The simplified socket helper classes help network programmers create socket programs with simpler statements and less coding—two important benefits for any programmer. This section introduces the C# socket helper classes. In Chapter 7, “Using the C# Sockets Helper Classes,” you’ll study detailed examples of how to use these classes in actual programs.

Here are the three helper classes used for socket programming:

Each one is designed to support a specific socket programming function and to simplify the interfaces required to program for that function. Obviously, the TcpClient and TcpListener classes are used for creating TCP client and server programs; the UdpClient class is used for creating UDP programs.

TcpClient

The methods of the TcpClient class are used to create client network programs that follow the connection-oriented network model. The TcpClient methods mirror those in normal socket programming, but many of the steps are compacted to simplify the programming task.

For starters, there are three ways to create a TcpClient object and connect it to a remote host, and each technique makes creating a socket easier than using the manual Socket class methods.

The default constructorThe default constructor format creates a socket on any available local port. You can then use the Connect() method to connect to a specified remote host:

TcpClient newclient = new TcpClient();
newclient.Connect("www.isp.net", 8000);

The first statement creates a new TcpClient object and binds it to a local address and port. The second statement connects the socket to a remote host address and port number. Notice that the remote host address can be specified as a hostname. The TcpClient class will automatically attempt to resolve the hostname to the proper IP address. That’s a lot of work already done for you!

A specific EndPoint object The second constructor format goes one step further and allows you to specify a specific local EndPoint object to use when creating the socket:

IPAddress ia = Dns.GetHostByName(
        Dns.GetHostName()).AddressList[0];
IPEndPoint iep = new IPEndPoint(ia, 10232);
TcpClient newclient2 = new TcpClient(iep);
newclient2.Connect("www.isp.net", 8000);

A specific remote host The third constructor format is the most common. It allows you to specify the remote host address and port to connect to within the constructor, removing the need to use the Connect() method:

TcpClient newclient3 = new TcpClient("www.isp.net", 8000);

In one easy step, you create a new TcpClient object to a random local port number and connect it to the specified remote host. Again, if you use a hostname for the host address, the TcpClient object will attempt to resolve it automatically. Creating a socket and connecting to a remote host with one statement—what a system!’

Once a TcpClient instance is created, you will probably want to send and receive data with it. The GetStream() method is used to create a NetworkStream object that allows you to send and receive bytes on the socket. Once you have a NetworkStream instance for the socket, it is a snap to use the standard stream Read() and Write() methods to move data into and out of the socket. This code fragment demonstrates assigning a NetworkStream object to the TcpClient instance and writing data to and reading it from the socket:

TcpClient newclient = new TcpClient("www.isp.net", 8000);
NetworkStream ns = newclient.GetStream();
byte[] outbytes = Encoding.ASCII.GetBytes("Testing");
ns.Write(outbytes, 0, outbytes.Length);
byte[] inbytes = new byte[1024];
ns.Read(inbytes, 0, inbytes.Length);
string instring = Encoding.ASCII.GetString(inbytes);
Console.WriteLine(instring);
ns.Close();
newclient.Close();'
Note 

As in the Unix socket world, you must remember to properly close the TcpClient object with the Close()method when you are done with it. Note that closing the NetworkStream object still leaves the TcpClient object open. This is a small detail that many novice network programmers miss.

TcpListener

Just as the TcpClient class simplifies client socket programs, the TcpListener class simplifies server programs; their class constructors are similar as well. Here are the three constructor formats:

  • TcpListener(int port)binds to a specific local port number

  • TcpListener(IPEndPoint ie)binds to a specific local EndPoint

  • TcpListener(IPAddress addr, int port) binds to a specific local IPAddress and port number

These three formats allow you to control how the underlying socket is created for the TcpListener object. Once the object is created, you can begin listening for new connection attempts using the Start() method.

After the Start() method, you must use either the AcceptSocket() or AcceptTcpClient() method to accept incoming connection attempts. As their names suggest, the two methods accept an incoming connection and return either a Socket or TcpClient object. You are already taking advantage of the TcpListener class, so you will probably want to use the AcceptTcpClient() method to create a new TcpClient object for the new connection.

Once the new TcpClient object is created for the connection, you can employ the standard TcpClient methods to begin communicating with the client. A sample code fragment would look like this:

TcpListener newserver = new TcpListener(9050);
newserver.Start();
TcpClient newclient = newserver.AcceptTcpClient();
NetworkStream ns = newclient.GetStream();
byte[] outbytes = Encoding.ASCII.GetBytes("Testing");
ns.Write(outbytes, 0, outbytes.Length);
byte[] inbytes = new byte[1024];
ns.Read(inbytes, 0, inbytes.Length);
string instring = Encoding.ASCII.GetString(inbytes);
Console.WriteLine(instring);
ns.Close();
newclient.Close();
newserver.Stop();

This program will block at the AcceptTcpClient() method, waiting for a new client connection. Once connected, the GetStream() method is used to create a NetworkStream object for reading and writing data to the connected socket.

Remember to close the NetworkStream as well as the TcpClient object when they are finished. You must use the Stop() method to close the TcpListener.

UdpClient

For applications that require a connectionless socket, the UdpClient class provides a simple interface to UDP sockets. You may be wondering why there is not a listener version of the UDP helper class. The answer is simple: you don’t need one. Remember, UDP is a connectionless protocol, so there is no such thing as a client or server; there are only UDP sockets either waiting for or sending data. You do not need to bind the UDP socket to a specific address and wait for incoming data.

The UdpClient constructors follow the same format as TcpClient—they allow you to specify the amount of information necessary to create the UDP socket or reference a remote address and UDP port.

The Receive() method allows you to receive data on the UDP port. There is no connection session established, so when a UDP port receives data, you do not necessarily know where it came from (unless you specified it in the UdpClient constructor). To compensate for this, the Receive() method includes an IPEndPoint parameter that is filled with the IP information from the remote host. This is done as follows:

UdpClient newconn = new UdpClient(8000);
IPEndPoint remoteclient = new IPEndPoint(IPAddress.Any, 0);
byte[] recv = newconn.Receive(ref remoteclient);
string data = Encoding.ASCII.GetString(recv);
ConsoleWriteLine("From: {0}", remoteclient.ToString());
ConsoleWriteLine(" Data: "{0}", data);
newconn.Close();

The UdpClient object is instantiated using a port number on which you want the application to accept UDP packets. Note that the remoteclient object is instantiated using the IPAddress.Any value. This is used as a dummy value that will be replaced with the information from the remote client in the Receive() method.

The Send() method has three formats. If the UdpClient object references a remote host address and port, the Send() method does not need to specify the destination of the data.

However, if the UdpClient object does not reference a remote host, the Send() method must do that. This can be accomplished with either an IPEndPoint object, or a string hostname or address value and an integer port number. Sending data would look like this:

UdpClient newclient = new UdpClient(8001);
IPEndPoint remotehost = new
   IPEndPoint(IPAddress.Parse("192.168.1.6"), 8001);
byte[] bytes = Encoding.ASCII.GetBytes("test string");
newclient.Send(bytes, bytes.Length, remotehost);
newclient.Close();

The port number used on the UdpClient constructor does not have to be the same as for the remote host, but it often helps to keep them the same in order to track the ports that are being used by particular applications. The remote host address information is stored in an IPEndPoint object and used as a parameter in the Send() method.


 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows