|
C# Asynchronous Server Program Example
Create a new console application project and you might want to use the solution name, AsyncTcpServerCS and project name, AsyncTcpServer as shown in the following Figure.
|
Next, rename the source file to AsyncServer to reflect the application that we are going to develop.
Add the following using directives.
using System; using System.Net; using System.Net.Sockets; using System.Collections; using System.Threading; using AsyncPacketClass; |
Next, add the reference to the AsyncPacketClass. Select project folder > Right click mouse > Select Add Reference context menu.
Browse the AsyncPacketClass project folder.
Browse the DLL file, select the file and click OK.
You can see the reference to the class has been added under the References folder. To make sure the reference to the AsyncPacketClass class is functioning, you can build this project. There should be no error in the Output window.
When you double click the AsyncPacketClass sub folder, all the object in the class will be shown in the Object Browser as shown below.
Next, add the public access modifier for the class.
Add the following usage() and the Main() methods codes which encapsulated in the AsyncServer class.
/// <summary> /// Displays simple usage information /// </summary> static public void usage() { Console.WriteLine("Executable_file_name [-a count] [-l address] [-p port]"); Console.WriteLine("Available options:"); Console.WriteLine(" -a count Number of simultaneous asynch Accepts (BeginAccept) allowed."); Console.WriteLine(" -l address Local address to create a TCP"); Console.WriteLine(" server on (can be specified multiple times."); Console.WriteLine(" -p port Local port number each server listens on."); Console.WriteLine(); }
/// <summary> /// This is the main program that parses the command line parameters and sets up each TCP /// listening socket by creating a TcpServer object to handle client connections to each /// listening endpoint. The TcpServer object creates a AcceptedConection object for each /// established connection which handles IO operations from each client. /// </summary> /// <param name="args"></param> static void Main(string[ ] args) { ArrayList listenInterfaces = new ArrayList(), tcpServerList = new ArrayList(); int asyncAcceptLimit = 10, listenPort = 5150;
// Parse the command line if (args.Length != 0) { for (int i = 0; i < args.Length; i++) { try { if ((args[i][0] == '-') || (args[i][0] == '/')) { switch (Char.ToLower(args[i][1])) { case 'a': // How many asynchronous accept (BeginAccepts) allowed simultaneously asyncAcceptLimit = System.Convert.ToInt32(args[++i]); break; case 'l': // Local interface(s) to bind to listenInterfaces.Add(IPAddress.Parse(args[++i])); break; case 'p': // Port on which to listen listenPort = System.Convert.ToInt32(args[++i]); break; default: usage(); return; } } } catch { usage(); return; } } } else { usage(); return; }
// Create an array of handles to signal when server sockets are finished Console.WriteLine("Creating an array of handles to signal when server sockets are finished..."); WaitHandle [ ] serverWaitHandles = new WaitHandle [ listenInterfaces.Count ]; // Create a TCP server socket for each local listen address passed to the application Console.WriteLine("Creating a TCP server socket for each local listen address passed to the application..."); for(int i=0; i < listenInterfaces.Count ;i++ ) { IPEndPoint listenEndPoint; TcpServer listenServer;
try { listenEndPoint = new IPEndPoint( (IPAddress) listenInterfaces[i], listenPort ); listenServer = new TcpServer( listenEndPoint, asyncAcceptLimit ); serverWaitHandles[ i ] = listenServer.serverDone; tcpServerList.Add( listenServer ); } catch ( Exception err ) { Console.WriteLine("Error: {0}", err.Message); } }
// Wait until all the TCP server sockets are done Console.WriteLine("Waiting until all the TCP server sockets are done..."); while ( true ) { if ( ManualResetEvent.WaitAll( serverWaitHandles, 10000, false )== false ) { // Wait timed out so print some statistics Console.WriteLine(" Client Count Byte Count"); Console.WriteLine(" Server Address Current/Total Sent/Received"); for(int i=0; i < tcpServerList.Count ;i++) { Console.WriteLine(" {0} {1} / {2} {3}/{4}", ((TcpServer)tcpServerList[i]).tcpSocket.LocalEndPoint.ToString().PadRight(20, ' '), ((TcpServer)tcpServerList[i]).currentClientCount.ToString().PadLeft(12, ' '), ((TcpServer)tcpServerList[i]).totalClientCount.ToString().PadRight(12, ' '), ((TcpServer)tcpServerList[i]).TotalSendBytes.ToString().PadLeft(12, ' '), ((TcpServer)tcpServerList[i]).TotalReceiveBytes.ToString().PadRight(12, ' ') ); } continue; } else { break; } } Console.WriteLine("All listen sockets have been signaled...closing listen sockets...");
for(int i=0; i < listenInterfaces.Count ;i++) { TcpServer listenServer = (TcpServer) tcpServerList[i];
listenServer.Shutdown(); listenServer.tcpSocket.Close(); } Console.WriteLine("Sleeping for 10000..."); Thread.Sleep( 10000 ); } |
Build and run the project.
![]() |
|
The following is the sample output when run from the command prompt.
In this project, we have included a reference to the AsyncPacketClass library. You can see the DLL file has been included in this project as shown in the following Figure.
The following sample output shows the server program run from the command prompt.
We will test this server with the client example that will be created in the next exercise.