11.11 Create a Multithreaded TCP Server


Problem

You want to create a TCP server that can simultaneously handle multiple TCP clients .

Solution

Use the AcceptTcpClient method of the TcpListener class. Every time a new client connects, start a new thread to handle the request and call TcpListener.AcceptTcpClient again.

Discussion

A single TCP endpoint (IP address and port) can serve multiple connections. In fact, the operating system takes care of most of the work for you. All you need to do is create a worker object on the server that will handle each connection on a separate thread.

For example, consider the basic TCP client and server classes shown in recipe 11.8. You can easily convert the server into a multithreaded server that supports multiple simultaneous connections. First create a class that will interact with an individual client, as shown in the following code:

 using System; using System.Net; using System.Net.Sockets; using System.IO; using System.Threading; using SharedComponent; public class ClientHandler {     private TcpClient client;     private string ID;     public ClientHandler(TcpClient client, string ID) {         this.client = client;         this.ID = ID;     }     public void Start() {         // Retrieve the network stream.         NetworkStream stream = client.GetStream();         // Create a BinaryWriter for writing to the stream.         BinaryWriter w = new BinaryWriter(stream);         // Create a BinaryReader for reading from the stream.         BinaryReader r = new BinaryReader(stream);         if (r.ReadString() == ClientMessages.RequestConnect) {             w.Write(ServerMessages.AcknowledgeOK);             Console.WriteLine(ID + ": Connection completed.");             while (r.ReadString() != ClientMessages.Disconnect) {}             Console.WriteLine(ID + ": Disconnect request received.");             w.Write(ServerMessages.Disconnect);         }else {             Console.WriteLine(ID + ": Could not complete connection.");         }         // Close the connection socket.         client.Close();         Console.WriteLine(ID + ": Client connection closed.");         Console.ReadLine();     } } 

Next modify the server code so that it loops continuously, creating new ClientHandler instances as required and launching them on new threads. Here's the revised code:

 public class TcpServerTest {     private static void Main() {         TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"),             8000);                   Console.WriteLine("Server: About to initialize port.");         listener.Start();         Console.WriteLine("Server: Listening for a connection...");                      int clientNum = 0;         while (true) {             try {                 // Wait for a connection request,                  // and return a TcpClient initialized for communication.                  TcpClient client = listener.AcceptTcpClient();                 Console.WriteLine("Server: Connection accepted.");                 // Create a new object to handle this connection.                 clientNum++;                 ClientHandler handler = new ClientHandler(client, "Client " +                   clientNum.ToString());                 // Start this object working on another thread.                 Thread handlerThread =                    new Thread(new ThreadStart(handler.Start));                 handlerThread.IsBackground = true;                 handlerThread.Start();                 // (You could also add the Handler and HandlerThread to                 // a collection to track client sessions.)             }catch (Exception err) {                 Console.WriteLine(err.ToString());             }         }     } } 

The following code shows the server-side transcript of a session with two clients:

 Server: About to initialize port. Server: Listening for a connection... Server: Connection accepted. Client 1: Connection completed. Server: Connection accepted. Client 2: Connection completed. Client 2: Disconnect request received. Client 2: Client connection closed. Client 1: Disconnect request received. Client 1: Client connection closed. 

You might want to add additional code to the network server so that it tracks the current worker objects in a collection. Doing so would allow the server to abort these tasks if it needs to shut down and enforce a maximum number of simultaneous clients.




C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net