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

来源:互联网 发布:超级基因优化液txt 编辑:程序博客网 时间:2024/05/20 23:29

原创性声明

本文作者:小竹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服务器

本文介绍

在.Net中,System.Net.Sockets 命名空间为需要严密控制网络访问的开发人员提供了 Windows Sockets (Winsock) 接口的托管实现。System.Net 命名空间中的所有其他网络访问类都建立在该套接字Socket实现之上,如TCPClient、TCPListener 和 UDPClient 类封装有关创建到 Internet 的 TCP 和 UDP 连接的详细信息;NetworkStream类则提供用于网络访问的基础数据流等,常见的许多Internet服务都可以见到Socket的踪影,如Telnet、Http、Email、Echo等,这些服务尽管通讯协议Protocol的定义不同,但是其基础的传输都是采用的Socket。 其实,Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。 
可见,在应用程序端或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据; 
针对Socket编程,.NET 框架的 Socket 类是 Winsock32 API 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,Socket 类方法只是将数据封送到它们的本机 Win32 副本中并处理任何必要的安全检查。如果你熟悉Winsock API函数,那么用Socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用Socket类开发windows 网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。

本节介绍使用Socket来实现一个高性能的异步UDP服务器,实际上UDP是不分客户机和服务器的,但是我们有的时候和服务器通讯就是使用UDP来进行的。

Socket异步UDP服务器

[csharp] view plain copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net;  
  6. using System.Net.Sockets;  
  7.   
  8. namespace NetFrame.Net.UDP.Sock.Asynchronous  
  9. {  
  10.     /// <summary>  
  11.     /// SOCKET实现异步UDP服务器  
  12.     /// </summary>  
  13.     public class AsyncSocketUDPServer  
  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<AsyncUDPSocketState> _clients;  
  35.   
  36.         private bool disposed = false;  
  37.   
  38.         /// <summary>  
  39.         /// 数据接受缓冲区  
  40.         /// </summary>  
  41.         private byte[] _recvBuffer;  
  42.  
  43.         #endregion  
  44.  
  45.         #region Properties  
  46.   
  47.         /// <summary>  
  48.         /// 服务器是否正在运行  
  49.         /// </summary>  
  50.         public bool IsRunning { getprivate set; }  
  51.         /// <summary>  
  52.         /// 监听的IP地址  
  53.         /// </summary>  
  54.         public IPAddress Address { getprivate set; }  
  55.         /// <summary>  
  56.         /// 监听的端口  
  57.         /// </summary>  
  58.         public int Port { getprivate set; }  
  59.         /// <summary>  
  60.         /// 通信使用的编码  
  61.         /// </summary>  
  62.         public Encoding Encoding { getset; }  
  63.  
  64.         #endregion  
  65.  
  66.         #region 构造函数  
  67.   
  68.         /// <summary>  
  69.         /// 异步Socket UDP服务器  
  70.         /// </summary>  
  71.         /// <param name="listenPort">监听的端口</param>  
  72.         public AsyncSocketUDPServer(int listenPort)  
  73.             : this(IPAddress.Any, listenPort,1024)  
  74.         {  
  75.         }  
  76.   
  77.         /// <summary>  
  78.         /// 异步Socket UDP服务器  
  79.         /// </summary>  
  80.         /// <param name="localEP">监听的终结点</param>  
  81.         public AsyncSocketUDPServer(IPEndPoint localEP)  
  82.             : this(localEP.Address, localEP.Port,1024)  
  83.         {  
  84.         }  
  85.   
  86.         /// <summary>  
  87.         /// 异步Socket UDP服务器  
  88.         /// </summary>  
  89.         /// <param name="localIPAddress">监听的IP地址</param>  
  90.         /// <param name="listenPort">监听的端口</param>  
  91.         /// <param name="maxClient">最大客户端数量</param>  
  92.         public AsyncSocketUDPServer(IPAddress localIPAddress, int listenPort, int maxClient)  
  93.         {  
  94.             this.Address = localIPAddress;  
  95.             this.Port = listenPort;  
  96.             this.Encoding = Encoding.Default;  
  97.   
  98.             _maxClient = maxClient;  
  99.             //_clients = new List<AsyncUDPSocketState>();  
  100.             _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);  
  101.   
  102.             _recvBuffer=new byte[_serverSock.ReceiveBufferSize];  
  103.         }  
  104.  
  105.         #endregion  
  106.  
  107.         #region Method  
  108.         /// <summary>  
  109.         /// 启动服务器  
  110.         /// </summary>  
  111.         /// <returns>异步TCP服务器</returns>  
  112.         public void Start()  
  113.         {  
  114.             if (!IsRunning)  
  115.             {  
  116.                 IsRunning = true;  
  117.                 _serverSock.Bind(new IPEndPoint(this.Address, this.Port));  
  118.                 //_serverSock.Connect(new IPEndPoint(IPAddress.Any, 0));  
  119.   
  120.                 AsyncSocketUDPState so = new AsyncSocketUDPState();  
  121.                 so.workSocket = _serverSock;  
  122.   
  123.                 _serverSock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None,  
  124.                     ref so.remote, new AsyncCallback(ReceiveDataAsync), null);  
  125.   
  126.   
  127.                 //EndPoint sender = new IPEndPoint(IPAddress.Any, 0);  
  128.   
  129.                 //_serverSock.BeginReceiveFrom(_recvBuffer, 0, _recvBuffer.Length, SocketFlags.None,  
  130.                 //    ref sender, new AsyncCallback(ReceiveDataAsync), sender);  
  131.   
  132.                 //BeginReceive 和 BeginReceiveFrom的区别是什么  
  133.                 /*_serverSock.BeginReceive(_recvBuffer, 0, _recvBuffer.Length, SocketFlags.None, 
  134.                     new AsyncCallback(ReceiveDataAsync), null);*/  
  135.             }  
  136.         }  
  137.   
  138.         /// <summary>  
  139.         /// 停止服务器  
  140.         /// </summary>  
  141.         public void Stop()  
  142.         {  
  143.             if (IsRunning)  
  144.             {  
  145.                 IsRunning = false;  
  146.                 _serverSock.Close();  
  147.                 //TODO 关闭对所有客户端的连接  
  148.   
  149.             }  
  150.         }  
  151.   
  152.         /// <summary>  
  153.         /// 接收数据的方法  
  154.         /// </summary>  
  155.         /// <param name="ar"></param>  
  156.         private void ReceiveDataAsync(IAsyncResult ar)  
  157.         {  
  158.             AsyncSocketUDPState so = ar.AsyncState as AsyncSocketUDPState;  
  159.             //EndPoint sender = new IPEndPoint(IPAddress.Any, 0);  
  160.             int len = -1;  
  161.             try  
  162.             {  
  163.                 len = _serverSock.EndReceiveFrom(ar, ref so.remote);  
  164.   
  165.                 //len = _serverSock.EndReceiveFrom(ar, ref sender);  
  166.   
  167.                 //EndReceiveFrom 和 EndReceive区别  
  168.                 //len = _serverSock.EndReceive(ar);  
  169.                 //TODO 处理数据  
  170.   
  171.                 //触发数据收到事件  
  172.                 RaiseDataReceived(so);  
  173.             }  
  174.             catch (Exception)  
  175.             {  
  176.                 //TODO 处理异常  
  177.                 RaiseOtherException(so);  
  178.             }  
  179.             finally  
  180.             {  
  181.                 if (IsRunning && _serverSock != null)  
  182.                     _serverSock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None,  
  183.                 ref so.remote, new AsyncCallback(ReceiveDataAsync), so);  
  184.             }  
  185.         }  
  186.         /// <summary>  
  187.         /// 发送数据  
  188.         /// </summary>  
  189.         /// <param name="msg"></param>  
  190.         /// <param name="remote"></param>  
  191.         public void Send(string msg,EndPoint remote)  
  192.         {  
  193.             byte[] data = Encoding.Default.GetBytes(msg);  
  194.             try  
  195.             {  
  196.                 RaisePrepareSend(null);  
  197.                 _serverSock.BeginSendTo(data, 0, data.Length, SocketFlags.None, remote, new AsyncCallback(SendDataEnd), _serverSock);  
  198.             }  
  199.             catch (Exception)  
  200.             {  
  201.                 //TODO 异常处理  
  202.                 RaiseOtherException(null);  
  203.             }  
  204.         }  
  205.   
  206.         private void SendDataEnd(IAsyncResult ar)  
  207.         {  
  208.             ((Socket)ar.AsyncState).EndSendTo(ar);  
  209.             RaiseCompletedSend(null);  
  210.         }  
  211.  
  212.         #endregion  
  213.  
  214.         #region 事件  
  215.         /// <summary>  
  216.         /// 接收到数据事件  
  217.         /// </summary>  
  218.         public event EventHandler<AsyncSocketUDPEventArgs> DataReceived;  
  219.   
  220.         private void RaiseDataReceived(AsyncSocketUDPState state)  
  221.         {  
  222.             if (DataReceived != null)  
  223.             {  
  224.                 DataReceived(thisnew AsyncSocketUDPEventArgs(state));  
  225.             }  
  226.         }  
  227.   
  228.         /// <summary>  
  229.         /// 发送数据前的事件  
  230.         /// </summary>  
  231.         public event EventHandler<AsyncSocketUDPEventArgs> PrepareSend;  
  232.   
  233.         /// <summary>  
  234.         /// 触发发送数据前的事件  
  235.         /// </summary>  
  236.         /// <param name="state"></param>  
  237.         private void RaisePrepareSend(AsyncSocketUDPState state)  
  238.         {  
  239.             if (PrepareSend != null)  
  240.             {  
  241.                 PrepareSend(thisnew AsyncSocketUDPEventArgs(state));  
  242.             }  
  243.         }  
  244.   
  245.         /// <summary>  
  246.         /// 数据发送完毕事件  
  247.         /// </summary>  
  248.         public event EventHandler<AsyncSocketUDPEventArgs> CompletedSend;  
  249.   
  250.         /// <summary>  
  251.         /// 触发数据发送完毕的事件  
  252.         /// </summary>  
  253.         /// <param name="state"></param>  
  254.         private void RaiseCompletedSend(AsyncSocketUDPState state)  
  255.         {  
  256.             if (CompletedSend != null)  
  257.             {  
  258.                 CompletedSend(thisnew AsyncSocketUDPEventArgs(state));  
  259.             }  
  260.         }  
  261.   
  262.         /// <summary>  
  263.         /// 网络错误事件  
  264.         /// </summary>  
  265.         public event EventHandler<AsyncSocketUDPEventArgs> NetError;  
  266.         /// <summary>  
  267.         /// 触发网络错误事件  
  268.         /// </summary>  
  269.         /// <param name="state"></param>  
  270.         private void RaiseNetError(AsyncSocketUDPState state)  
  271.         {  
  272.             if (NetError != null)  
  273.             {  
  274.                 NetError(thisnew AsyncSocketUDPEventArgs(state));  
  275.             }  
  276.         }  
  277.   
  278.         /// <summary>  
  279.         /// 异常事件  
  280.         /// </summary>  
  281.         public event EventHandler<AsyncSocketUDPEventArgs> OtherException;  
  282.         /// <summary>  
  283.         /// 触发异常事件  
  284.         /// </summary>  
  285.         /// <param name="state"></param>  
  286.         private void RaiseOtherException(AsyncSocketUDPState state, string descrip)  
  287.         {  
  288.             if (OtherException != null)  
  289.             {  
  290.                 OtherException(thisnew AsyncSocketUDPEventArgs(descrip, state));  
  291.             }  
  292.         }  
  293.         private void RaiseOtherException(AsyncSocketUDPState state)  
  294.         {  
  295.             RaiseOtherException(state, "");  
  296.         }  
  297.         #endregion  
  298.  
  299.         #region Close  
  300.         /// <summary>  
  301.         /// 关闭一个与客户端之间的会话  
  302.         /// </summary>  
  303.         /// <param name="state">需要关闭的客户端会话对象</param>  
  304.         public void Close(AsyncSocketUDPState state)  
  305.         {  
  306.             if (state != null)  
  307.             {  
  308.                 //_clients.Remove(state);  
  309.                 //_clientCount--;  
  310.                 //TODO 触发关闭事件  
  311.             }  
  312.         }  
  313.         /// <summary>  
  314.         /// 关闭所有的客户端会话,与所有的客户端连接会断开  
  315.         /// </summary>  
  316.         public void CloseAllClient()  
  317.         {  
  318.             //foreach (AsyncUDPSocketState client in _clients)  
  319.             //{  
  320.             //    Close(client);  
  321.             //}  
  322.             //_clientCount = 0;  
  323.             //_clients.Clear();  
  324.         }  
  325.  
  326.         #endregion  
  327.  
  328.         #region 释放  
  329.         /// <summary>  
  330.         /// Performs application-defined tasks associated with freeing,   
  331.         /// releasing, or resetting unmanaged resources.  
  332.         /// </summary>  
  333.         public void Dispose()  
  334.         {  
  335.             Dispose(true);  
  336.             GC.SuppressFinalize(this);  
  337.         }  
  338.   
  339.         /// <summary>  
  340.         /// Releases unmanaged and - optionally - managed resources  
  341.         /// </summary>  
  342.         /// <param name="disposing"><c>true</c> to release   
  343.         /// both managed and unmanaged resources; <c>false</c>   
  344.         /// to release only unmanaged resources.</param>  
  345.         protected virtual void Dispose(bool disposing)  
  346.         {  
  347.             if (!this.disposed)  
  348.             {  
  349.                 if (disposing)  
  350.                 {  
  351.                     try  
  352.                     {  
  353.                         Stop();  
  354.                         if (_serverSock != null)  
  355.                         {  
  356.                             _serverSock = null;  
  357.                         }  
  358.                     }  
  359.                     catch (SocketException)  
  360.                     {  
  361.                         //TODO  
  362.                         RaiseOtherException(null);  
  363.                     }  
  364.                 }  
  365.                 disposed = true;  
  366.             }  
  367.         }  
  368.         #endregion  
  369.     }  
  370. }  

会话封装类

[csharp] view plain copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net;  
  6. using System.Net.Sockets;  
  7.   
  8. namespace NetFrame.Net.UDP.Sock.Asynchronous  
  9. {  
  10.     public class AsyncSocketUDPState  
  11.     {  
  12.         // Client   socket.  
  13.         public Socket workSocket = null;  
  14.         // Size of receive buffer.  
  15.         public const int BufferSize = 1024;  
  16.         // Receive buffer.  
  17.         public byte[] buffer = new byte[BufferSize];  
  18.         // Received data string.  
  19.         public StringBuilder sb = new StringBuilder();  
  20.   
  21.         public EndPoint remote = new IPEndPoint(IPAddress.Any, 0);  
  22.     }  
  23. }  
Socket异步UDP服务器事件参数类

[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.UDP.Sock.Asynchronous  
  7. {  
  8.     /// <summary>  
  9.     /// SOCKET 异步UDP 事件类  
  10.     /// </summary>  
  11.     public class AsyncSocketUDPEventArgs : EventArgs  
  12.     {  
  13.         /// <summary>  
  14.         /// 提示信息  
  15.         /// </summary>  
  16.         public string _msg;  
  17.   
  18.         /// <summary>  
  19.         /// 客户端状态封装类  
  20.         /// </summary>  
  21.         public AsyncSocketUDPState _state;  
  22.   
  23.         /// <summary>  
  24.         /// 是否已经处理过了  
  25.         /// </summary>  
  26.         public bool IsHandled { getset; }  
  27.   
  28.         public AsyncSocketUDPEventArgs(string msg)  
  29.         {  
  30.             this._msg = msg;  
  31.             IsHandled = false;  
  32.         }  
  33.         public AsyncSocketUDPEventArgs(AsyncSocketUDPState state)  
  34.         {  
  35.             this._state = state;  
  36.             IsHandled = false;  
  37.         }  
  38.         public AsyncSocketUDPEventArgs(string msg, AsyncSocketUDPState state)  
  39.         {  
  40.             this._msg = msg;  
  41.             this._state = state;  
  42.             IsHandled = false;  
  43.         }  
  44.     }  
  45. }  

本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处
阅读全文
0 0
原创粉丝点击