网络编程资料总结(二)----Tcp多线程服务器和客户端的实现时间:2021-06-06 13:47:34服务端: 第一种方法:using System;using System.IO;using System.Net.Sockets;using System.Text;using System.Collections;using System.Threading;class ClientConnectionPool { // Creates a synchronized wrapper around the Queue. private Queue SyncdQ = Queue.Synchronized( new Queue() ); public void Enqueue(ClientHandler client) { SyncdQ.Enqueue(client) ; } public ClientHandler Dequeue() { return (ClientHandler) ( SyncdQ.Dequeue() ) ; } public int Count { get { return SyncdQ.Count ; } } public object SyncRoot { get { return SyncdQ.SyncRoot ; } } } // class ClientConnectionPool class ClientService { const int NUM_OF_THREAD = 10; private ClientConnectionPool ConnectionPool ; private bool ContinueProcess = false ; private Thread [] ThreadTask = new Thread[NUM_OF_THREAD] ; public ClientService(ClientConnectionPool ConnectionPool) { this.ConnectionPool = ConnectionPool ; } public void Start() { ContinueProcess = true ; // Start threads to handle Client Task for ( int i = 0 ; i < ThreadTask.Length ; i++) { ThreadTask[i] = new Thread( new ThreadStart(this.Process) ); ThreadTask[i].Start() ; } } private void Process() { while ( ContinueProcess ) { ClientHandler client = null ; lock( ConnectionPool.SyncRoot ) { if ( ConnectionPool.Count > 0 ) client = ConnectionPool.Dequeue() ; } if ( client != null ) { client.Process() ; // Provoke client // if client still connect, schedufor later processingle it if ( client.Alive ) ConnectionPool.Enqueue(client) ; } Thread.Sleep(100) ; } } public void Stop() { ContinueProcess = false ; for ( int i = 0 ; i < ThreadTask.Length ; i++) { if ( ThreadTask[i] != null && ThreadTask[i].IsAlive ) ThreadTask[i].Join() ; } // Close all client connections while ( ConnectionPool.Count > 0 ) { ClientHandler client = ConnectionPool.Dequeue() ; client.Close() ; Console.WriteLine("Client connection is closed!") ; } } } // class ClientServicepublic class SynchronousSocketListener { private const int portNum = 10116 ; public static void StartListening() { ClientService ClientTask ; // Client Connections Pool ClientConnectionPool ConnectionPool = new ClientConnectionPool() ; // Client Task to handle client requests ClientTask = new ClientService(ConnectionPool) ; ClientTask.Start() ; TcpListener listener = new TcpListener(portNum); try { listener.Start(); int TestingCycle = 3 ; // Number of testing cycles int ClientNbr = 0 ; // Start listening for connections. Console.WriteLine("Waiting for a connection..."); while ( TestingCycle > 0 ) { TcpClient handler = listener.AcceptTcpClient(); if ( handler != null) { Console.WriteLine("Client#{0} accepted!", ++ClientNbr) ; // An incoming connection needs to be processed. ConnectionPool.Enqueue( new ClientHandler(handler) ) ; --TestingCycle ; } else break; } listener.Stop(); // Stop client requests handling ClientTask.Stop() ; } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("/nHit enter to continue..."); Console.Read(); } public static int Main(String[] args) { StartListening(); return 0; }}class ClientHandler {private TcpClient ClientSocket ; private NetworkStream networkStream ;bool ContinueProcess = false ; private byte[] bytes; // Data buffer for incoming data. private StringBuilder sb = new StringBuilder(); // Received data string.private string data = null; // Incoming data from the client.public ClientHandler (TcpClient ClientSocket) {ClientSocket.ReceiveTimeout = 100 ; // 100 milisecondsthis.ClientSocket = ClientSocket ; networkStream = ClientSocket.GetStream(); bytes = new byte[ClientSocket.ReceiveBufferSize]; ContinueProcess = true ;}public void Process() { try { int BytesRead = networkStream.Read(bytes, 0, (int) bytes.Length); if ( BytesRead > 0 ) // There might be more data, so store the data received so far. sb.Append(Encoding.ASCII.GetString(bytes, 0, BytesRead)); else // All the data has arrived; put it in response. ProcessDataReceived() ; } catch ( IOException ) { // All the data has arrived; put it in response. ProcessDataReceived() ; } catch ( SocketException ) { networkStream.Close() ; ClientSocket.Close(); ContinueProcess = false ; Console.WriteLine( "Conection is broken!"); } } // Process() private void ProcessDataReceived() { if ( sb.Length > 0 ) {bool bQuit = ( String.Compare( sb.ToString(), "quit", true ) == 0 ) ;data = sb.ToString() ; sb.Length = 0 ; // Clear bufferConsole.WriteLine( "Text received from client:") ; Console.WriteLine(data) ;StringBuilder response = new StringBuilder( ) ;response.Append( "Received at " ) ;response.Append( DateTime.Now.ToString() ) ;response.Append( "/r/n" ) ;response.Append( data ) ; // Echo the data back to the client. byte[] sendBytes = Encoding.ASCII.GetBytes(response.ToString()); networkStream.Write(sendBytes, 0, sendBytes.Length); // Client stop processing if ( bQuit ) { networkStream.Close() ; ClientSocket.Close(); ContinueProcess = false ; } } } public void Close() { networkStream.Close() ; ClientSocket.Close(); } public bool Alive { get { return ContinueProcess ; } } } // class ClientHandler 第二种方法: using System;using System.IO;using System.Net.Sockets;using System.Text;using System.Collections;using System.Threading;public class SynchronousSocketListener { private const int portNum = 10116 ; private static ArrayList ClientSockets ; private static bool ContinueReclaim = true; private static Thread ThreadReclaim ; public static void StartListening() { ClientSockets = new ArrayList() ; ThreadReclaim = new Thread( new ThreadStart(Reclaim) ); ThreadReclaim.Start() ; TcpListener listener = new TcpListener(portNum); try { listener.Start(); int TestingCycle = 3 ; int ClientNbr = 0 ; // Start listening for connections. Console.WriteLine("Waiting for a connection..."); while ( TestingCycle > 0 ) { TcpClient handler = listener.AcceptTcpClient(); if ( handler != null) { Console.WriteLine("Client#{0} accepted!", ++ClientNbr) ; // An incoming connection needs to be processed. lock( ClientSockets.SyncRoot ) { int i = ClientSockets.Add( new ClientHandler(handler) ) ; ((ClientHandler) ClientSockets[i]).Start() ; } --TestingCycle ; } else break; } listener.Stop(); ContinueReclaim = false ; ThreadReclaim.Join() ; foreach ( Object Client in ClientSockets ) { ( (ClientHandler) Client ).Stop() ; } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("/nHit enter to continue..."); Console.Read(); } private static void Reclaim() { while (ContinueReclaim) { lock( ClientSockets.SyncRoot ) { for ( int x = ClientSockets.Count-1 ; x >= 0 ; x-- ) { Object Client = ClientSockets[x] ; if ( !( ( ClientHandler ) Client ).Alive ) { ClientSockets.Remove( Client ) ; Console.WriteLine("A client left") ; } } } Thread.Sleep(200) ; } } public static int Main(String[] args) { StartListening(); return 0; }}class ClientHandler {TcpClient ClientSocket ;bool ContinueProcess = false ;Thread ClientThread ;public ClientHandler (TcpClient ClientSocket) {this.ClientSocket = ClientSocket ;}public void Start() {ContinueProcess = true ;ClientThread = new Thread ( new ThreadStart(Process) ) ;ClientThread.Start() ;}private void Process() {// Incoming data from the client. string data = null;// Data buffer for incoming data.byte[] bytes;if ( ClientSocket != null ) { NetworkStream networkStream = ClientSocket.GetStream(); ClientSocket.ReceiveTimeout = 100 ; // 1000 milisecondswhile ( ContinueProcess ) { bytes = new byte[ClientSocket.ReceiveBufferSize]; try { int BytesRead = networkStream.Read(bytes, 0, (int) ClientSocket.ReceiveBufferSize); if ( BytesRead > 0 ) { data = Encoding.ASCII.GetString(bytes, 0, BytesRead); // Show the data on the console. Console.WriteLine( "Text received : {0}", data); // Echo the data back to the client. byte[] sendBytes = Encoding.ASCII.GetBytes(data); networkStream.Write(sendBytes, 0, sendBytes.Length); if ( data == "quit" ) break ; } } catch ( IOException ) { } // Timeout catch ( SocketException ) { Console.WriteLine( "Conection is broken!"); break ; } Thread.Sleep(200) ; } // while ( ContinueProcess ) networkStream.Close() ; ClientSocket.Close();}} // Process()public void Stop() {ContinueProcess = false ; if ( ClientThread != null && ClientThread.IsAlive ) ClientThread.Join() ;} public bool Alive { get { return ( ClientThread != null && ClientThread.IsAlive ); } } } // class ClientHandler 第三种方法: using System;using System.IO;using System.Net.Sockets;using System.Text;using System.Collections;using System.Threading;class SharedState { public bool ContinueProcess ; public int NumberOfClients ; public AutoResetEvent Ev ;}public class SynchronousSocketListener { private const int portNum = 10116 ; private static SharedState SharedStateObj ; public static void StartListening() { SharedStateObj = new SharedState() ; SharedStateObj.ContinueProcess = true ; SharedStateObj.NumberOfClients = 0 ; SharedStateObj.Ev = new AutoResetEvent(false) ; TcpListener listener = new TcpListener(portNum); try { listener.Start(); int TestingCycle = 3 ; int ClientNbr = 0 ; // Start listening for connections. Console.WriteLine("Waiting for a connection..."); while ( TestingCycle > 0 ) { TcpClient handler = listener.AcceptTcpClient(); if ( handler != null) { Console.WriteLine("Client#{0} accepted!", ++ClientNbr) ; // An incoming connection needs to be processed. ClientHandler client = new ClientHandler(handler) ; // Add no. of clients by one Interlocked.Increment(ref SharedStateObj.NumberOfClients ); // Queue client handling task to thread pool ThreadPool.QueueUserWorkItem(new WaitCallback(client.Process), SharedStateObj); --TestingCycle ; } else break; } listener.Stop(); } catch (Exception e) { Console.WriteLine(e.ToString()); } // Stop and wait all client connections to end SharedStateObj.ContinueProcess = false ; SharedStateObj.Ev.WaitOne() ; Console.WriteLine("/nHit enter to continue..."); Console.Read(); } public static int Main(String[] args) { StartListening(); return 0; }}class ClientHandler {private TcpClient ClientSocket ;public ClientHandler (TcpClient ClientSocket) {this.ClientSocket = ClientSocket ;}public void Process(Object O) { SharedState SharedStateObj = (SharedState) O ; // Incoming data from the client. string data = null;bool bQuit = false ; // Data buffer for incoming data.byte[] bytes; NetworkStream networkStream = ClientSocket.GetStream(); ClientSocket.ReceiveTimeout = 100 ; // 1000 miliseconds bytes = new byte[ClientSocket.ReceiveBufferSize]; try { int BytesRead = networkStream.Read(bytes, 0, (int) ClientSocket.ReceiveBufferSize); if ( BytesRead > 0 ) { data = Encoding.ASCII.GetString(bytes, 0, BytesRead); // Show the data on the console. Console.WriteLine( "Text received : {0}", data); // Echo the data back to the client. byte[] sendBytes = Encoding.ASCII.GetBytes(data); networkStream.Write(sendBytes, 0, sendBytes.Length);bQuit = ( String.Compare( data, "quit", true ) == 0 ) ;} } catch ( IOException ) { } // Timeout catch ( SocketException ) {bQuit = true ; Console.WriteLine( "Conection is broken!"); }// Schedule task again if ( SharedStateObj.ContinueProcess && !bQuit ) ThreadPool.QueueUserWorkItem(new WaitCallback(this.Process), SharedStateObj);else { networkStream.Close() ; ClientSocket.Close(); // Deduct no. of clients by one Interlocked.Decrement(ref SharedStateObj.NumberOfClients ); Console.WriteLine("A client left, number of connections is {0}", SharedStateObj.NumberOfClients) ;} // Signal main process if this is the last client connections main thread requested to stop. if ( !SharedStateObj.ContinueProcess && SharedStateObj.NumberOfClients == 0 ) SharedStateObj.Ev.Set();} // Process() } // class ClientHandler 客户端: using System;using System.Net.Sockets;using System.Text;class TcpClientTest { private const int portNum = 10116 ; static public void Main() { TcpClient tcpClient = new TcpClient(); try{ tcpClient.Connect("localhost", portNum); NetworkStream networkStream = tcpClient.GetStream(); if (networkStream.CanWrite && networkStream.CanRead){ String DataToSend = "" ; while ( DataToSend != "quit" ) { Console.WriteLine("/nType a text to be sent:");DataToSend = Console.ReadLine() ;if ( DataToSend.Length == 0 ) break ; Byte[] sendBytes = Encoding.ASCII.GetBytes(DataToSend); networkStream.Write(sendBytes, 0, sendBytes.Length); // Reads the NetworkStream into a byte buffer. byte[] bytes = new byte[tcpClient.ReceiveBufferSize]; int BytesRead = networkStream.Read(bytes, 0, (int) tcpClient.ReceiveBufferSize); // Returns the data received from the host to the console. string returndata = Encoding.ASCII.GetString(bytes, 0 , BytesRead); Console.WriteLine("This is what the host returned to you: /r/n{0}", returndata); } networkStream.Close(); tcpClient.Close(); } else if (!networkStream.CanRead){ Console.WriteLine("You can not write data to this stream"); tcpClient.Close(); } else if (!networkStream.CanWrite){ Console.WriteLine("You can not read data from this stream"); tcpClient.Close(); } } catch (SocketException) { Console.WriteLine("Sever not available!"); } catch (System.IO.IOException) { Console.WriteLine("Sever not available!"); } catch (Exception e ) { Console.WriteLine(e.ToString()); } } // Main() } // class TcpClientTest {