Declaration of originality
This article author: Xiao Bamboo zz This article address: http://blog.csdn.net/zhujunxxxxx reprint please indicate the source.
Introduction I previously wrote a IOCP article: http://blog.csdn.net/zhujunxxxxx/article/details/43573879 This is better than the asynchronous socket, because it is reusable objects.
In C #, Microsoft has provided TcpListener and tcpclient to implement TCP communication, which has been written in some of the better asynchronous server code http://www.cnblogs.com/gaochundong/archive/2013/ 04/14/csharp_async_tcp_server.html This blogger blog quality is really high, I often browse his blog there is always a lot of surprises to me, he used TcpListener to implement the asynchronous server.
My socket version is essentially no different from his, just rewrite a little bit, so put a piece of code here is, many do not explain
Code Server Core Code AsyncServer.cs
<summary>///Async Socket Server///</summary> public class Asyncserver:idisposable {#reg Ion fields///<summary>///The maximum number of client connections allowed by the server program///</summary> private int _maxclien T <summary>///Current number of connections///</summary> private int _clientcount; <summary>///server use asynchronous socket///</summary> private socket _serversock; <summary>///client Session list///</summary> private list<session> _clients; private bool disposed = false; #endregion #region Properties//<summary>//Whether the server is running///</summary> PU blic bool IsRunning {get; private set;} <summary>////Listening IP address///</summary> public IPAddress address {get; private set;} <summary>///Listening ports///</summary> public int Port {get; private set;} <summary>////</summary> public Encoding Encoding {get; set;} #endregion #region ctors//<summary>//asynchronous socket TCP///</summary> <param name= "listenport" > Monitored ports </param> public asyncserver (int listenport): This (I Paddress.any, listenport,1024) {}//<summary>//asynchronous Socket TCP Server///</sum mary>//<param name= "localep" > Monitored endpoints </param> public asyncserver (IPEndPoint localEP) : This (localep.address, localep.port,1024) {}//<summary>//Async Socket TCP Server </summary>//<param name= "localipaddress" > monitored IP address </param>///<param Name= "Li Stenport "> Monitored ports </param>//<param name=" maxclient "> Maximum number of clients </param> Public Asyncserver (IPAddress localipaddress, int. Listenport,int maxclient) {this. Address = localipaddress; This. Port = Listenport; This. Encoding = Encoding.default; _maxclient = maxclient; _clients = new list<session> (); _serversock = new Socket (localipaddress.addressfamily, SocketType.Stream, protocoltype.tcp); #endregion #region Server///<summary>///boot server///</summary>/ <returns> Asynchronous TCP Server </returns> public asyncserver Start () {if (! isrunning) {isrunning = true; _serversock.bind (New IPEndPoint (this. Address, this. Port)); _serversock.listen (1024); _serversock.beginaccept (New AsyncCallback (handleacceptconnected), _serversock); } return this; }///<summary>//Start server///</summary>//<param name= "Backlog" >//The maximum length of the pending connection sequence allowed by//server///</param> <returns> Asynchronous TCP Server </returns> public asyncserver Start (int backlog) {if (! isrunning) {isrunning = true; _serversock.bind (New IPEndPoint (this. Address, this. Port)); _serversock.listen (backlog); _serversock.beginaccept (New AsyncCallback (handleacceptconnected), _serversock); } return this; }///<summary>//Stop server///</summary>//<returns> Asynchronous TCP Server </RETURNS&G T Public Asyncserver Stop () {if (isrunning) {isrunning = false; _serversock.close (); TODO closes the connection to all clients} return this; #endregion #region Receive//<summary>//Processing client connections</summary>//<param name= "ar" ></param> private void handleacceptconnected (Iasyncresu Lt ar) {if (isrunning) {Socket server = (socket) ar. asyncstate; Socket client = server. Endaccept (AR); Check whether the maximum number of allowed clients is reached if (_clientcount = = _maxclient) {//todo trigger Event Raiseserverexception (NULL); } else {Session session = new session (client); Lock (_clients) {_clients. ADD (session); _clientcount++; Raiseclientconnected (session); Triggers a client Connection event} session. Recvdatabuffer = new Byte[client. Receivebuffersize]; Start accepting data from the client. BeginReceive (session. Recvdatabuffer, 0, SESsion. Recvdatabuffer.length, Socketflags.none, New AsyncCallback (Handledatareceived), session); }//Accept the next request server. BeginAccept (New AsyncCallback (handleacceptconnected), AR. asyncstate); }}///<summary>///Processing client data///</summary>//<param name= "AR" >< ;/param> private void handledatareceived (IAsyncResult ar) {if (isrunning) { Session Session = (session) AR. asyncstate; Socket client = session. Clientsocket; try {//If the asynchronous receive is started two times, so when the client exits//will be executed two times endreceive int recv = client. EndReceive (AR); if (recv = = 0) {//todo trigger event (Close client) CloseSession (session ); Raiseneterror (session); ReturN //todo processing the data that has been read PS: Data in the session of the Recvdatabuffer raisedatareceived (session); TODO trigger data Receive event} catch (SocketException ex) { TODO exception Handling Raiseneterror (session); Finally {//continues to receive the data client from the clients. BeginReceive (session. Recvdatabuffer, 0, session. Recvdatabuffer.length, Socketflags.none, New AsyncCallback (Handledatareceived), session); }}} #endregion #region Send//<summary>///&L t;/summary>//<param Name= "Session" > Client session receiving Data </param>//<param name= "Data" > Packet < ;/param> public void Send (Session session, byte[] data) {Send (session). Clientsocket,data); }//<summAry>/////asynchronously send data to the specified client///</summary>//<param name= "Client" > Clients </param> <param name= "Data" > Messages </param> public void Send (Socket client, byte[] data) {if (! isrunning) throw new InvalidProgramException ("This TCP Scoket server have not been started."); if (client = = null) throw new ArgumentNullException ("Client"); if (data = null) throw new ArgumentNullException ("Data"); Client. BeginSend (data, 0, data. Length, Socketflags.none, New AsyncCallback (Senddataend), client); }///<summary>///Send data completion processing function///</summary>//<param name= "AR" > Target client sock et</param> private void Senddataend (IAsyncResult ar) {(Socket) ar. asyncstate). EndSend (AR); } #endregion #region Events///<summary>///Received data event </summary> public event eventhandler<eventargs> datareceived; private void Raisedatareceived (session session) {if (datareceived! = null) { DataReceived (This, new Asynceventargs (session)); }}////<summary>//Client connection established Event///</summary> public event EventHandler <AsyncEventArgs> clientconnected; <summary>//connection to client disconnected Event///</summary> public event Eventhandler<asynceventargs > clientdisconnected; <summary>///Trigger Client Connection Events///</summary>//<param Name= "session" ></param> private void Raiseclientconnected (session session) {if (clientconnected! = null) { Clientconnected (This, new Asynceventargs (session)); }}///<summary>//Trigger Client Connection Disconnect Event///</summary>//<param name= "client" ></param> private void raiseclientdisconnected (Socket client {if (clientdisconnected! = null) {clientdisconnected (this, new Asynceventa RGS ("Disconnected")); }}///<summary>//Network error events///</summary> public event Eventhandler<as Ynceventargs> Neterror; <summary>///Trigger Network error events///</summary>//<param name= "Client" ></param> private void Raiseneterror (session session) {if (neterror! = null) {Ne Terror (This, new Asynceventargs (session)); }}///<summary>///exception Event///</summary> public event Eventhandler<asyn Ceventargs> serverexception; <summary>///Trigger Exception events///</summary>//<param name= "Client" ></PARAM> private void Raiseserverexception (session session) {if (serverexception! = null) { Serverexception (This, new Asynceventargs (session)); }} #endregion #region Close//<summary>///Shut down a session with the client//</summ ary>//<param name= "Closeclient" > Client Session object that needs to be closed </param> public void CloseSession (Session Sess ION) {if (session! = NULL) {session. Datagram = null; Session. Recvdatabuffer = null; _clients. Remove (session); _clientcount--; TODO triggers the Shutdown event session. Close (); }}///<summary>///Close all client sessions, and all client connections will be disconnected///</summary> public void Cl Oseallclient () {foreach (Session client in _clients) {closesession (client); } _clientcount = 0; _clients. Clear (); }///<summary>//performs application-defined tasks associated with freeing,///releasing, or resetting unmanaged 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 Disp OSE (bool disposing) {if (!this.disposed) {if (disposing) { try {Stop (); if (_serversock! = null) { _serversock = null; }} catch (SocketException ex) {//todo Raiseserverexception (NULL); }} disposed = true; }} #endregion}
A session class is used to encapsulate the connection to the client Session,cs
<summary>///client-server session class///</summary> public class Session {#region Field// <summary>///Receive data buffer///</summary> private byte[] _recvbuffer; <summary>///client messages sent to server///NOTE: In some cases the message may be a fragment of the message but not complete///</summary> Private String _datagram; <summary>//Client socket///</summary> private socket _clientsock; #endregion #region Properties///<summary>//Receive data buffers///</summary> public byte [] Recvdatabuffer {get {return _recvbuffer; } set {_recvbuffer = value; }}///<summary>///Access Message///</summary> public string Datagram {get {return _datagram; } set {_datagram = value; }}///<summary>//Get the socket object associated with the client session////</summary> public socket Clie Ntsocket {get {return _clientsock; }} #endregion///<summary>//constructor///</summary>//<param N Ame= "Clisock" > Session using the Socket connection </param> public session (socket Clisock) {_clientsock = Cliso ck }///<summary>///closed session///</summary> public void Close () {// Turn off acceptance and transmission of data _clientsock.shutdown (Socketshutdown.both); Cleanup resources _clientsock.close (); } }
Event class
Class Asynceventargs:eventargs {///<summary>//// </summary> Public string _msg; Public Session _sessions; <summary>///whether the/// </summary> public bool ishandled {get; set;} Public Asynceventargs (String msg) { this._msg = msg; ishandled = false; } Public Asynceventargs (Session session) { this._sessions = session; ishandled = false; } Public Asynceventargs (String msg, session session) { this._msg = msg; This._sessions = Session; ishandled = false; } }
The next time the socket version of the asynchronous client code is mended
C # Asynchronous socket TCP Server implementation