C#网络编程系列文章(一)之Socket实现异步TCP服务器

原创性声明

本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处

文章系列目录

C#网络编程系列文章(一)之Socket实现异步TCP服务器 

C#网络编程系列文章(二)之Socket实现同步TCP服务器

C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

C#网络编程系列文章(四)之TcpListener实现同步TCP服务器

C#网络编程系列文章(五)之Socket实现异步UDP服务器

C#网络编程系列文章(六)之Socket实现同步UDP服务器

C#网络编程系列文章(七)之UdpClient实现异步UDP服务器

C#网络编程系列文章(八)之UdpClient实现同步UDP服务器

代码下载地址

http://download.csdn.net/detail/zhujunxxxxx/8510991

开篇

本人因为对于网络编程的喜爱,经常性的使用c#编写各类服务器(e.g TCP服务器,UDP服务器),但是基本上都是搞着玩,网上也有很多讲c#网络编程的文章,当然我也参考了很多作者写的文章。看了这篇文章以后再也不用导出找资料了。微笑

本系列文章会依次介绍使用Socket实现的异步TCP服务器同步TCP服务器异步UDP服务器同步UDP服务器 and 使用TcpListener和UdpClient实现的异步TCP服务器同步TCP服务器异步UDP服务器同步UDP服务器


Socket异步TCP服务器

相信搞过网络编程的人来说这个TCP一点也不陌生吧,在C#中微软已经帮我们封装过了一个TcpListener和TcpClient这两个类了,实现了对于套接字的封装,但是呢实际上还是不怎么好用,所以我们用Socket来实现一个异步的TCP服务器。

在本文中我只给出服务器端代码,客户端代码自己可以找找别处,毕竟我只是为了写出一个好的服务器端

下面是代码

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net.Sockets;  
  6. using System.Net;  
  7.   
  8. namespace NetFrame.Net.TCP.Sock.Asynchronous  
  9. {  
  10.     /// <summary>  
  11.     /// Socket实现的异步TCP服务器  
  12.     /// </summary>  
  13.     public class AsyncSocketTCPServer : IDisposable  
  14.     {  
  15.         #region Fields  
  16.         /// <summary>  
  17.         /// 服务器程序允许的最大客户端连接数  
  18.         /// </summary>  
  19.         private int _maxClient;  
  20.   
  21.         /// <summary>  
  22.         /// 当前的连接的客户端数  
  23.         /// </summary>  
  24.         private int _clientCount;  
  25.   
  26.         /// <summary>  
  27.         /// 服务器使用的异步socket  
  28.         /// </summary>  
  29.         private Socket _serverSock;  
  30.   
  31.         /// <summary>  
  32.         /// 客户端会话列表  
  33.         /// </summary>  
  34.         private List<AsyncSocketState> _clients;  
  35.   
  36.         private bool disposed = false;  
  37.  
  38.         #endregion  
  39.  
  40.         #region Properties  
  41.   
  42.         /// <summary>  
  43.         /// 服务器是否正在运行  
  44.         /// </summary>  
  45.         public bool IsRunning { getprivate set; }  
  46.         /// <summary>  
  47.         /// 监听的IP地址  
  48.         /// </summary>  
  49.         public IPAddress Address { getprivate set; }  
  50.         /// <summary>  
  51.         /// 监听的端口  
  52.         /// </summary>  
  53.         public int Port { getprivate set; }  
  54.         /// <summary>  
  55.         /// 通信使用的编码  
  56.         /// </summary>  
  57.         public Encoding Encoding { getset; }  
  58.  
  59.  
  60.         #endregion  
  61.  
  62.         #region 构造函数  
  63.   
  64.         /// <summary>  
  65.         /// 异步Socket TCP服务器  
  66.         /// </summary>  
  67.         /// <param name="listenPort">监听的端口</param>  
  68.         public AsyncSocketTCPServer(int listenPort)  
  69.             : this(IPAddress.Any, listenPort,1024)  
  70.         {  
  71.         }  
  72.   
  73.         /// <summary>  
  74.         /// 异步Socket TCP服务器  
  75.         /// </summary>  
  76.         /// <param name="localEP">监听的终结点</param>  
  77.         public AsyncSocketTCPServer(IPEndPoint localEP)  
  78.             : this(localEP.Address, localEP.Port,1024)  
  79.         {  
  80.         }  
  81.   
  82.         /// <summary>  
  83.         /// 异步Socket TCP服务器  
  84.         /// </summary>  
  85.         /// <param name="localIPAddress">监听的IP地址</param>  
  86.         /// <param name="listenPort">监听的端口</param>  
  87.         /// <param name="maxClient">最大客户端数量</param>  
  88.         public AsyncSocketTCPServer(IPAddress localIPAddress, int listenPort,int maxClient)  
  89.         {  
  90.             this.Address = localIPAddress;  
  91.             this.Port = listenPort;  
  92.             this.Encoding = Encoding.Default;  
  93.   
  94.             _maxClient = maxClient;  
  95.             _clients = new List<AsyncSocketState>();  
  96.             _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);  
  97.         }  
  98.  
  99.         #endregion  
  100.  
  101.         #region Method  
  102.   
  103.         /// <summary>  
  104.         /// 启动服务器  
  105.         /// </summary>  
  106.         public void Start()  
  107.         {  
  108.             if (!IsRunning)  
  109.             {  
  110.                 IsRunning = true;  
  111.                 _serverSock.Bind(new IPEndPoint(this.Address, this.Port));  
  112.                 _serverSock.Listen(1024);  
  113.                 _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);  
  114.             }  
  115.         }  
  116.   
  117.         /// <summary>  
  118.         /// 启动服务器  
  119.         /// </summary>  
  120.         /// <param name="backlog">  
  121.         /// 服务器所允许的挂起连接序列的最大长度  
  122.         /// </param>  
  123.         public void Start(int backlog)  
  124.         {  
  125.             if (!IsRunning)  
  126.             {  
  127.                 IsRunning = true;  
  128.                 _serverSock.Bind(new IPEndPoint(this.Address, this.Port));  
  129.                 _serverSock.Listen(backlog);  
  130.                 _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);  
  131.             }  
  132.         }  
  133.   
  134.         /// <summary>  
  135.         /// 停止服务器  
  136.         /// </summary>  
  137.         public void Stop()  
  138.         {  
  139.             if (IsRunning)  
  140.             {  
  141.                 IsRunning = false;  
  142.                 _serverSock.Close();  
  143.                 //TODO 关闭对所有客户端的连接  
  144.   
  145.             }  
  146.         }  
  147.   
  148.         /// <summary>  
  149.         /// 处理客户端连接  
  150.         /// </summary>  
  151.         /// <param name="ar"></param>  
  152.         private void HandleAcceptConnected(IAsyncResult ar)  
  153.         {  
  154.             if (IsRunning)  
  155.             {  
  156.                 Socket server = (Socket)ar.AsyncState;  
  157.                 Socket client = server.EndAccept(ar);  
  158.   
  159.                 //检查是否达到最大的允许的客户端数目  
  160.                 if (_clientCount >= _maxClient)  
  161.                 {  
  162.                     //C-TODO 触发事件  
  163.                     RaiseOtherException(null);  
  164.                 }  
  165.                 else  
  166.                 {  
  167.                     AsyncSocketState state = new AsyncSocketState(client);  
  168.                     lock (_clients)  
  169.                     {  
  170.                         _clients.Add(state);  
  171.                         _clientCount++;  
  172.                         RaiseClientConnected(state); //触发客户端连接事件  
  173.                     }  
  174.                     state.RecvDataBuffer = new byte[client.ReceiveBufferSize];  
  175.                     //开始接受来自该客户端的数据  
  176.                     client.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None,  
  177.                      new AsyncCallback(HandleDataReceived), state);  
  178.                 }  
  179.                 //接受下一个请求  
  180.                 server.BeginAccept(new AsyncCallback(HandleAcceptConnected), ar.AsyncState);  
  181.             }  
  182.         }  
  183.         /// <summary>  
  184.         /// 处理客户端数据  
  185.         /// </summary>  
  186.         /// <param name="ar"></param>  
  187.         private void HandleDataReceived(IAsyncResult ar)  
  188.         {  
  189.             if (IsRunning)  
  190.             {  
  191.                 AsyncSocketState state = (AsyncSocketState)ar.AsyncState;  
  192.                 Socket client = state.ClientSocket;  
  193.                 try  
  194.                 {  
  195.                     //如果两次开始了异步的接收,所以当客户端退出的时候  
  196.                     //会两次执行EndReceive  
  197.                     int recv = client.EndReceive(ar);  
  198.                     if (recv == 0)  
  199.                     {  
  200.                         //C- TODO 触发事件 (关闭客户端)  
  201.                         Close(state);  
  202.                         RaiseNetError(state);  
  203.                         return;  
  204.                     }  
  205.                     //TODO 处理已经读取的数据 ps:数据在state的RecvDataBuffer中  
  206.   
  207.                     //C- TODO 触发数据接收事件  
  208.                     RaiseDataReceived(state);  
  209.                 }  
  210.                 catch (SocketException)  
  211.                 {  
  212.                     //C- TODO 异常处理  
  213.                     RaiseNetError(state);  
  214.                 }  
  215.                 finally  
  216.                 {  
  217.                     //继续接收来自来客户端的数据  
  218.                     client.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None,  
  219.                      new AsyncCallback(HandleDataReceived), state);  
  220.                 }  
  221.             }  
  222.         }  
  223.   
  224.         /// <summary>  
  225.         /// 发送数据  
  226.         /// </summary>  
  227.         /// <param name="state">接收数据的客户端会话</param>  
  228.         /// <param name="data">数据报文</param>  
  229.         public void Send(AsyncSocketState state, byte[] data)  
  230.         {  
  231.             RaisePrepareSend(state);  
  232.             Send(state.ClientSocket, data);  
  233.         }  
  234.   
  235.         /// <summary>  
  236.         /// 异步发送数据至指定的客户端  
  237.         /// </summary>  
  238.         /// <param name="client">客户端</param>  
  239.         /// <param name="data">报文</param>  
  240.         public void Send(Socket client, byte[] data)  
  241.         {  
  242.             if (!IsRunning)  
  243.                 throw new InvalidProgramException("This TCP Scoket server has not been started.");  
  244.   
  245.             if (client == null)  
  246.                 throw new ArgumentNullException("client");  
  247.   
  248.             if (data == null)  
  249.                 throw new ArgumentNullException("data");  
  250.             client.BeginSend(data, 0, data.Length, SocketFlags.None,  
  251.              new AsyncCallback(SendDataEnd), client);  
  252.         }  
  253.   
  254.         /// <summary>  
  255.         /// 发送数据完成处理函数  
  256.         /// </summary>  
  257.         /// <param name="ar">目标客户端Socket</param>  
  258.         private void SendDataEnd(IAsyncResult ar)  
  259.         {  
  260.             ((Socket)ar.AsyncState).EndSend(ar);  
  261.             RaiseCompletedSend(null);  
  262.         }  
  263.         #endregion  
  264.  
  265.         #region 事件  
  266.   
  267.         /// <summary>  
  268.         /// 与客户端的连接已建立事件  
  269.         /// </summary>  
  270.         public event EventHandler<AsyncSocketEventArgs> ClientConnected;  
  271.         /// <summary>  
  272.         /// 与客户端的连接已断开事件  
  273.         /// </summary>  
  274.         public event EventHandler<AsyncSocketEventArgs> ClientDisconnected;  
  275.   
  276.         /// <summary>  
  277.         /// 触发客户端连接事件  
  278.         /// </summary>  
  279.         /// <param name="state"></param>  
  280.         private void RaiseClientConnected(AsyncSocketState state)  
  281.         {  
  282.             if (ClientConnected != null)  
  283.             {  
  284.                 ClientConnected(thisnew AsyncSocketEventArgs(state));  
  285.             }  
  286.         }  
  287.         /// <summary>  
  288.         /// 触发客户端连接断开事件  
  289.         /// </summary>  
  290.         /// <param name="client"></param>  
  291.         private void RaiseClientDisconnected(Socket client)  
  292.         {  
  293.             if (ClientDisconnected != null)  
  294.             {  
  295.                 ClientDisconnected(thisnew AsyncSocketEventArgs("连接断开"));  
  296.             }  
  297.         }  
  298.   
  299.         /// <summary>  
  300.         /// 接收到数据事件  
  301.         /// </summary>  
  302.         public event EventHandler<AsyncSocketEventArgs> DataReceived;  
  303.   
  304.         private void RaiseDataReceived(AsyncSocketState state)  
  305.         {  
  306.             if (DataReceived != null)  
  307.             {  
  308.                 DataReceived(thisnew AsyncSocketEventArgs(state));  
  309.             }  
  310.         }  
  311.   
  312.         /// <summary>  
  313.         /// 发送数据前的事件  
  314.         /// </summary>  
  315.         public event EventHandler<AsyncSocketEventArgs> PrepareSend;  
  316.   
  317.         /// <summary>  
  318.         /// 触发发送数据前的事件  
  319.         /// </summary>  
  320.         /// <param name="state"></param>  
  321.         private void RaisePrepareSend(AsyncSocketState state)  
  322.         {  
  323.             if (PrepareSend != null)  
  324.             {  
  325.                 PrepareSend(thisnew AsyncSocketEventArgs(state));  
  326.             }  
  327.         }  
  328.   
  329.         /// <summary>  
  330.         /// 数据发送完毕事件  
  331.         /// </summary>  
  332.         public event EventHandler<AsyncSocketEventArgs> CompletedSend;  
  333.           
  334.         /// <summary>  
  335.         /// 触发数据发送完毕的事件  
  336.         /// </summary>  
  337.         /// <param name="state"></param>  
  338.         private void RaiseCompletedSend(AsyncSocketState state)  
  339.         {  
  340.             if (CompletedSend != null)  
  341.             {  
  342.                 CompletedSend(thisnew AsyncSocketEventArgs(state));  
  343.             }  
  344.         }  
  345.   
  346.         /// <summary>  
  347.         /// 网络错误事件  
  348.         /// </summary>  
  349.         public event EventHandler<AsyncSocketEventArgs> NetError;  
  350.         /// <summary>  
  351.         /// 触发网络错误事件  
  352.         /// </summary>  
  353.         /// <param name="state"></param>  
  354.         private void RaiseNetError(AsyncSocketState state)  
  355.         {  
  356.             if (NetError != null)  
  357.             {  
  358.                 NetError(thisnew AsyncSocketEventArgs(state));  
  359.             }  
  360.         }  
  361.   
  362.         /// <summary>  
  363.         /// 异常事件  
  364.         /// </summary>  
  365.         public event EventHandler<AsyncSocketEventArgs> OtherException;  
  366.         /// <summary>  
  367.         /// 触发异常事件  
  368.         /// </summary>  
  369.         /// <param name="state"></param>  
  370.         private void RaiseOtherException(AsyncSocketState state, string descrip)  
  371.         {  
  372.             if (OtherException != null)  
  373.             {  
  374.                 OtherException(thisnew AsyncSocketEventArgs(descrip, state));  
  375.             }  
  376.         }  
  377.         private void RaiseOtherException(AsyncSocketState state)  
  378.         {  
  379.             RaiseOtherException(state, "");  
  380.         }  
  381.         #endregion  
  382.  
  383.         #region Close  
  384.         /// <summary>  
  385.         /// 关闭一个与客户端之间的会话  
  386.         /// </summary>  
  387.         /// <param name="state">需要关闭的客户端会话对象</param>  
  388.         public void Close(AsyncSocketState state)  
  389.         {  
  390.             if (state != null)  
  391.             {  
  392.                 state.Datagram = null;  
  393.                 state.RecvDataBuffer = null;  
  394.   
  395.                 _clients.Remove(state);  
  396.                 _clientCount--;  
  397.                 //TODO 触发关闭事件  
  398.                 state.Close();  
  399.             }  
  400.         }  
  401.         /// <summary>  
  402.         /// 关闭所有的客户端会话,与所有的客户端连接会断开  
  403.         /// </summary>  
  404.         public void CloseAllClient()  
  405.         {  
  406.             foreach (AsyncSocketState client in _clients)  
  407.             {  
  408.                 Close(client);  
  409.             }  
  410.             _clientCount = 0;  
  411.             _clients.Clear();  
  412.         }  
  413.         #endregion  
  414.  
  415.         #region 释放  
  416.         /// <summary>  
  417.         /// Performs application-defined tasks associated with freeing,   
  418.         /// releasing, or resetting unmanaged resources.  
  419.         /// </summary>  
  420.         public void Dispose()  
  421.         {  
  422.             Dispose(true);  
  423.             GC.SuppressFinalize(this);  
  424.         }  
  425.   
  426.         /// <summary>  
  427.         /// Releases unmanaged and - optionally - managed resources  
  428.         /// </summary>  
  429.         /// <param name="disposing"><c>true</c> to release   
  430.         /// both managed and unmanaged resources; <c>false</c>   
  431.         /// to release only unmanaged resources.</param>  
  432.         protected virtual void Dispose(bool disposing)  
  433.         {  
  434.             if (!this.disposed)  
  435.             {  
  436.                 if (disposing)  
  437.                 {  
  438.                     try  
  439.                     {  
  440.                         Stop();  
  441.                         if (_serverSock != null)  
  442.                         {  
  443.                             _serverSock = null;  
  444.                         }  
  445.                     }  
  446.                     catch (SocketException)  
  447.                     {  
  448.                         //TODO  
  449.                         RaiseOtherException(null);  
  450.                     }  
  451.                 }  
  452.                 disposed = true;  
  453.             }  
  454.         }  
  455.         #endregion  
  456.     }  
  457. }  

事件参数类

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace NetFrame.Net.TCP.Sock.Asynchronous  
  7. {  
  8.     /// <summary>  
  9.     /// 异步Socket TCP事件参数类  
  10.     /// </summary>  
  11.     public class AsyncSocketEventArgs:EventArgs  
  12.     {  
  13.         /// <summary>  
  14.         /// 提示信息  
  15.         /// </summary>  
  16.         public string _msg;  
  17.   
  18.         /// <summary>  
  19.         /// 客户端状态封装类  
  20.         /// </summary>  
  21.         public AsyncSocketState _state;  
  22.   
  23.         /// <summary>  
  24.         /// 是否已经处理过了  
  25.         /// </summary>  
  26.         public bool IsHandled { getset; }  
  27.   
  28.         public AsyncSocketEventArgs(string msg)  
  29.         {  
  30.             this._msg = msg;  
  31.             IsHandled = false;  
  32.         }  
  33.         public AsyncSocketEventArgs(AsyncSocketState state)  
  34.         {  
  35.             this._state = state;  
  36.             IsHandled = false;  
  37.         }  
  38.         public AsyncSocketEventArgs(string msg, AsyncSocketState state)  
  39.         {  
  40.             this._msg = msg;  
  41.             this._state = state;  
  42.             IsHandled = false;  
  43.         }  
  44.     }  
  45. }  

用户状态封装

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net.Sockets;  
  6.   
  7. namespace NetFrame.Net.TCP.Sock.Asynchronous  
  8. {  
  9.     /// <summary>  
  10.     /// 异步SOCKET TCP 中用来存储客户端状态信息的类  
  11.     /// </summary>  
  12.     public class AsyncSocketState  
  13.     {  
  14.         #region 字段  
  15.         /// <summary>  
  16.         /// 接收数据缓冲区  
  17.         /// </summary>  
  18.         private byte[] _recvBuffer;  
  19.   
  20.         /// <summary>  
  21.         /// 客户端发送到服务器的报文  
  22.         /// 注意:在有些情况下报文可能只是报文的片断而不完整  
  23.         /// </summary>  
  24.         private string _datagram;  
  25.   
  26.         /// <summary>  
  27.         /// 客户端的Socket  
  28.         /// </summary>  
  29.         private Socket _clientSock;  
  30.  
  31.         #endregion  
  32.  
  33.         #region 属性  
  34.   
  35.         /// <summary>  
  36.         /// 接收数据缓冲区   
  37.         /// </summary>  
  38.         public byte[] RecvDataBuffer  
  39.         {  
  40.             get  
  41.             {  
  42.                 return _recvBuffer;  
  43.             }  
  44.             set  
  45.             {  
  46.                 _recvBuffer = value;  
  47.             }  
  48.         }  
  49.   
  50.         /// <summary>  
  51.         /// 存取会话的报文  
  52.         /// </summary>  
  53.         public string Datagram  
  54.         {  
  55.             get  
  56.             {  
  57.                 return _datagram;  
  58.             }  
  59.             set  
  60.             {  
  61.                 _datagram = value;  
  62.             }  
  63.         }  
  64.   
  65.         /// <summary>  
  66.         /// 获得与客户端会话关联的Socket对象  
  67.         /// </summary>  
  68.         public Socket ClientSocket  
  69.         {  
  70.             get  
  71.             {  
  72.                 return _clientSock;  
  73.   
  74.             }  
  75.         }  
  76.  
  77.  
  78.         #endregion  
  79.   
  80.         /// <summary>  
  81.         /// 构造函数  
  82.         /// </summary>  
  83.         /// <param name="cliSock">会话使用的Socket连接</param>  
  84.         public AsyncSocketState(Socket cliSock)  
  85.         {  
  86.             _clientSock = cliSock;  
  87.         }  
  88.   
  89.         /// <summary>  
  90.         /// 初始化数据缓冲区  
  91.         /// </summary>  
  92.         public void InitBuffer()  
  93.         {  
  94.             if (_recvBuffer == null&&_clientSock!=null)  
  95.             {  
  96.                 _recvBuffer=new byte[_clientSock.ReceiveBufferSize];  
  97.             }  
  98.         }  
  99.   
  100.         /// <summary>  
  101.         /// 关闭会话  
  102.         /// </summary>  
  103.         public void Close()  
  104.         {  
  105.   
  106.             //关闭数据的接受和发送  
  107.             _clientSock.Shutdown(SocketShutdown.Both);  
  108.   
  109.             //清理资源  
  110.             _clientSock.Close();  
  111.         }  
  112.     }  
  113. }  

本文作者:小竹zz 本文地址 http://blog.csdn.net/zhujunxxxxx/article/details/44258719  转载请注明出处
相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页