Lecture 14: Multi-Client TCP Servers Objectives:: Connection Acceptor Connection Handler
Lecture 14: Multi-Client TCP Servers Objectives:: Connection Acceptor Connection Handler
Objectives:
Learn how to create multi-client TCP servers using the Thread class
Learn how to create multi-client TCP servers using the ThreadPool
class
Learn how to create multi-client TCP servers using asynchronous
methods
Introduction
We can also use threads to allow a server to maintain more than one
session – with multiple clients, at the same time.
Each time a client connects; the “connection acceptor” accepts the client
and then performs the following:
creates an instance of the “connection handler”
creates a separate thread, associating it with the connection handler
instance and
starts the thread.
The connection handler instance is responsible for communicating with
the client throughout the session.
Example 1:
The following example shows a multi-client echo client-server system.
class MultiThreadedTcpServer
{
public static void Main(string[] args)
{
int port = 9070;
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, port);
server.Bind(endpoint);
server.Listen(10);
Console.WriteLine("Waiting for clients on port " + port);
while(true) {
try {
Socket client = server.Accept();
ConnectionHandler handler = new ConnectionHandler(client);
class ConnectionHandler {
writer.WriteLine("Welcome to my server");
writer.Flush();
string input;
while(true) {
input = reader.ReadLine();
if (input.Length == 0 || input.ToLower() == "exit")
break;
writer.WriteLine(input);
writer.Flush();
}
ns.Close();
client.Close();
connections--;
Console.WriteLine("Client disconnected: {0} active connections",
connections);
} catch(Exception) {
connections--;
Console.WriteLine("Client disconnected: {0} active connections",
connections);
}
}
}
The above server can be tested using any of the Tcp echo client
discussed earlier.
Firing a thread to handle each client without any control as we did in the
above example is a sure way to crash a system.
The following are some of the methods of the ThreadPool class. All the
methods are static:
GetAvailableThreads Retrieves the difference between the maximum
number of thread pool threads, returned by
GetMaxThreads, and the number currently active.
GetMaxThreads Retrieves the number of requests to the thread
pool that can be active concurrently. All requests
above that number remain queued until thread
pool threads become available.
QueueUserWorkIte Overloaded. Queues a method for execution. The
m method executes when a thread pool thread
becomes available.
Exampe 2:
The following example modifies example 1 above to use ThreadPool.
while(true) {
try {
Socket client = server.Accept();
ConnectionHandler handler = new ConnectionHandler(client);
ThreadPool.QueueUserWorkItem(new
WaitCallback(handler.HandleConnection));
} catch(Exception) {
Console.WriteLine("Connection failed on port "+port);
}
}
}
public void HandleConnection(Object state) {...}
Example 3:
The following example uses asynchronous socket methods to
implement a windows-based asynchronous TCP echo client and server.
public MultiClientAsyncEchoServer(){
InitializeComponent();
}
void InitializeComponent() {
}
}