C # network programming series (iii) TcpListener Implement Asynchronous TCP server,

Source: Internet
Author: User

C # network programming series (iii) TcpListener Implement Asynchronous TCP server,
Originality statement

Author: Xiaozhu zz this article address http://blog.csdn.net/zhujunxxxxx/article/details/44258719 reprint please indicate the source

This article introduces

The TcpListener class provides some simple methods for listening to and receiving incoming connection requests in the blocking synchronous mode. You can use TcpClient or Socket to connect to TcpListener. You can use IPEndPoint, local IP address, and port number, or only the port number to create a TcpListener. You can specify the local IP address as Any and the local port number as 0 (if you want the basic service provider to assign these values to you ). If you choose to do this, you can use the LocalEndpoint attribute after connecting to the socket to identify the specified information. You can use the Start method to Start listening for incoming connection requests. Start will queue incoming connections until you call the Stop method or it has completed MaxConnections queuing. You can use AcceptSocket or AcceptTcpClient to extract connections from the incoming connection request queue. These two methods will be blocked. To avoid blocking, You can first use the Pending method to determine whether there are available connection requests in the queue.

Although TcpListener is already well encapsulated, we use it to construct a relatively good asynchronous TCP server. Here we still give the code in the server, just like in the previous two chapters, the comments in the Code are very detailed. I will also give the relevant encapsulation classes.

TcpListener asynchronous TCP server code
Using System; using System. collections. generic; using System. linq; using System. text; using System. net. sockets; using System. net; namespace NetFrame. net. TCP. listener. asynchronous {// <summary> // TcpListener implements Asynchronous TCP server // </summary> public class AsyncTCPServer: IDisposable {# region Fields /// <summary> // maximum number of client connections allowed by the server program /// </summary> private int _ maxClient; /// <summary> /// number of clients currently connected /// </summ Ary> private int _ clientCount; // <summary> // asynchronous TcpListener used by the server // </summary> private TcpListener _ listener; /// <summary> /// Client Session List /// </summary> private List <Object> _ clients; private bool disposed = false; # endregion # region Properties // <summary> // whether the server is running // </summary> public bool IsRunning {get; private set ;} /// <summary> /// IP Address of the listener /// </summary> public IPAddress Address {Get; private set ;}//< summary> /// listener Port //</summary> public int Port {get; private set ;} /// <summary> // Encoding used for communication /// </summary> public Encoding {get; set ;} # endregion # region constructor // <summary> // asynchronous TCP server // </summary> /// <param name = "listenPort"> listener port </param> public AsyncTCPServer (int listenPort): this (IPAddress. any, listenPort) {}/// <summary> /// asynchronous TCP server /// </su Mmary> // <param name = "localEP"> listener endpoint </param> public AsyncTCPServer (IPEndPoint localEP): this (localEP. address, localEP. port) {}/// <summary> /// asynchronous TCP server /// </summary> /// <param name = "localIPAddress"> listener IP address </param>/ // <param name = "listenPort"> listener port </param> public AsyncTCPServer (IPAddress localIPAddress, int listenPort) {Address = localIPAddress; Port = listenPort; this. encoding = Encodin G. default; _ clients = new List <Object> (); _ listener = new TcpListener (Address, Port); _ listener. allowNatTraversal (true) ;}# endregion # region Method /// <summary> /// Start the server /// </summary> public void Start () {if (! IsRunning) {IsRunning = true; _ listener. start (); _ listener. beginAcceptTcpClient (new AsyncCallback (HandleTcpClientAccepted), _ listener );}} /// <summary> /// start the server /// </summary> /// <param name = "backlog"> /// the connection sequence that the server allows to suspend maximum length // </param> public void Start (int backlog) {if (! IsRunning) {IsRunning = true; _ listener. start (backlog); _ listener. beginAcceptTcpClient (new AsyncCallback (HandleTcpClientAccepted), _ listener) ;}/// <summary> // Stop the server /// </summary> public void Stop () {if (IsRunning) {IsRunning = false; _ listener. stop (); lock (_ clients) {// close all clients to connect to CloseAllClient ();}}} /// <summary> /// function for processing client connection /// </summary> /// <param name = "ar"> </param> private vo Id HandleTcpClientAccepted (IAsyncResult ar) {if (IsRunning) {// TcpListener tcpListener = (TcpListener) ar. asyncState; TcpClient client = _ listener. endAcceptTcpClient (ar); byte [] buffer = new byte [client. receiveBufferSize]; TCPClientState state = new TCPClientState (client, buffer); lock (_ clients) {_ clients. add (state); RaiseClientConnected (state);} NetworkStream = state. networkStream; // Enabled Reads data stream asynchronously. beginRead (state. buffer, 0, state. buffer. length, HandleDataReceived, state); _ listener. beginAcceptTcpClient (new AsyncCallback (HandleTcpClientAccepted), ar. asyncState );}} /// <summary> // callback function for data reception // </summary> /// <param name = "ar"> </param> private void HandleDataReceived (IAsyncResult ar) {if (IsRunning) {TCPClientState state = (TCPClientState) ar. asyncState; NetworkStream strea M = state. networkStream; int recv = 0; try {recv = stream. endRead (ar) ;}catch {recv = 0;} if (recv = 0) {// connection has been closed lock (_ clients) {_ clients. remove (state); // trigger the client connection disconnection event RaiseClientDisconnected (state); return ;}// reset ed byte and trigger event notification byte [] buff = new byte [recv]; buffer. blockCopy (state. buffer, 0, buff, 0, recv); // triggers the Data Receiving Event RaiseDataReceived (st Ate); // continue listening for tcp datax packets stream. beginRead (state. buffer, 0, state. buffer. length, HandleDataReceived, state );}} /// <summary> /// send data /// </summary> /// <param name = "state"> client session for receiving data </param> // /<param name = "data"> data packet </param> public void Send (TCPClientState state, byte [] data) {RaisePrepareSend (state); Send (state. tcpClient, data) ;}/// <summary> /// send data asynchronously to the specified client/ /// </Summary> /// <param name = "client"> client </param> /// <param name = "data"> message </param> public void send (TcpClient client, byte [] data) {if (! IsRunning) throw new InvalidProgramException ("This TCP Scoket server has not been started. "); if (client = null) throw new ArgumentNullException (" client "); if (data = null) throw new ArgumentNullException (" data "); client. getStream (). beginWrite (data, 0, data. length, SendDataEnd, client );} /// <summary> /// processing function for data sending completion /// </summary> /// <param name = "ar"> target client Socket </param> private void SendDataEnd (IAsyncResult ar) {(TcpClient) ar. asyncState ). getStream (). endWrite (ar); RaiseCompletedSend (null );} # endregion # region event // <summary> // Events established with the client connection // </summary> public event EventHandler <AsyncEventArgs> ClientConnected; /// <summary> /// disconnection event with the client /// </summary> public event EventHandler <AsyncEventArgs> ClientDisconnected; /// <summary> /// trigger the client connection event /// </summary> /// <param name = "stat E "> </param> private void RaiseClientConnected (TCPClientState state) {if (ClientConnected! = Null) {ClientConnected (this, new AsyncEventArgs (state ));}} /// <summary> /// trigger the client connection disconnection event /// </summary> /// <param name = "client"> </param> private void RaiseClientDisconnected (TCPClientState state) {if (ClientDisconnected! = Null) {ClientDisconnected (this, new AsyncEventArgs ("disconnected "));}} /// <summary> /// receives the data event // </summary> public event EventHandler <AsyncEventArgs> DataReceived; private void Merge (TCPClientState state) {if (DataReceived! = Null) {DataReceived (this, new AsyncEventArgs (state ));}} /// <summary> /// event before data sending /// </summary> public event EventHandler <AsyncEventArgs> PrepareSend; /// <summary> /// trigger the event before data sending /// </summary> /// <param name = "state"> </param> private void RaisePrepareSend (TCPClientState state) {if (PrepareSend! = Null) {PrepareSend (this, new AsyncEventArgs (state ));}} /// <summary> /// data sending completion event /// </summary> public event EventHandler <AsyncEventArgs> CompletedSend; /// <summary> /// trigger the event of data sending completion /// </summary> /// <param name = "state"> </param> private void RaiseCompletedSend (TCPClientState state) {if (CompletedSend! = Null) {CompletedSend (this, new AsyncEventArgs (state ));}} /// <summary> // network error event // </summary> public event EventHandler <AsyncEventArgs> NetError; /// <summary> /// trigger a network error event /// </summary> /// <param name = "state"> </param> private void RaiseNetError (TCPClientState state) {if (NetError! = Null) {NetError (this, new AsyncEventArgs (state ));}} /// <summary> // exception event // </summary> public event EventHandler <AsyncEventArgs> OtherException; /// <summary> /// trigger an exception event /// </summary> /// <param name = "state"> </param> private void RaiseOtherException (TCPClientState state, string descrip) {if (OtherException! = Null) {OtherException (this, new AsyncEventArgs (descrip, state);} private void RaiseOtherException (TCPClientState state) {RaiseOtherException (state ,"");} # endregion # region Close /// <summary> // Close a session with the client /// </summary> /// <param name = "state"> required closed Client Session Object </param> public void Close (TCPClientState state) {if (state! = Null) {state. close (); _ clients. remove (state); _ clientCount --; // TODO trigger Close event }}/// <summary> // close all client sessions, connection to all clients will be disconnected /// </summary> public void CloseAllClient () {foreach (TCPClientState client in _ clients) {Close (client);} _ clientCount = 0; _ clients. clear () ;}# endregion # region release // <summary> // Performs application-defined tasks associated with freeing, // releasing, or resetting u Nmanaged resources. /// </summary> public void Dispose () {Dispose (true); GC. suppressFinalize (this );} /// <summary> /// Releases unmanaged and-optionally-managed resources // </summary> /// <param name = "disposing"> <c> true </c> to release // both managed and unmanaged resources; <c> false </c> // to release only unmanaged resources. </param> protected virtual void Dispose (bool disposing) {if (! This. disposed) {if (disposing) {try {Stop (); if (_ listener! = Null) {_ listener = null;} catch (SocketException) {// TODO RaiseOtherException (null) ;}} disposed = true ;}# endregion }}
Client processing Encapsulation
Using System; using System. collections. generic; using System. linq; using System. text; using System. net. sockets; namespace NetFrame. net. TCP. listener. asynchronous {public class TCPClientState {// <summary> // TcpClient related to the client /// </summary> public TcpClient {get; private set ;} /// <summary> /// obtain the Buffer // </summary> public byte [] Buffer {get; private set ;} /// <summary> /// obtain the network stream /// </summary> public NetworkStream {get {return TcpClient. getStream () ;}} public TCPClientState (TcpClient tcpClient, byte [] buffer) {if (tcpClient = null) throw new ArgumentNullException ("tcpClient "); if (buffer = null) throw new ArgumentNullException ("buffer"); this. tcpClient = tcpClient; this. buffer = buffer;} // <summary> /// Close /// </summary> public void Close () {// disable TcpClient for receiving and sending data. close (); Buffer = null ;}}}
Server event parameters
Using System; using System. collections. generic; using System. linq; using System. text; namespace NetFrame. net. TCP. listener. asynchronous {// <summary> // Asynchronous TcpListener TCP server event parameter class /// </summary> public class AsyncEventArgs: eventArgs {// <summary> /// message // </summary> public string _ msg; /// <summary> /// client status encapsulation class /// </summary> public TCPClientState _ state; /// <summary> /// whether it has been processed /// </summary> public bool IsHandled {get; set;} public AsyncEventArgs (string msg) {this. _ msg = msg; IsHandled = false;} public AsyncEventArgs (TCPClientState state) {this. _ state = state; IsHandled = false;} public AsyncEventArgs (string msg, TCPClientState state) {this. _ msg = msg; this. _ state = state; IsHandled = false ;}}}

Author: Xiaozhu zz this article address http://blog.csdn.net/zhujunxxxxx/article/details/44258719 reprint please indicate the source


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.