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

29 篇文章 0 订阅

原创性声明

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

本文介绍

UdpClient 类在同步阻塞模式中为发送和接收无连接的 UDP 数据包而提供了简单的方法。因为 UDP 是一种无连接的传输协议,所以你不需要在发送和接收数据之前建立任何远程主机连接。你只需要按照下列方式来建立默认的远程主机选项:
使用远程主机名称和端口号作为参数来创建 UdpClient 类的实例。
创建 UdpClient 类的实例然后调用 Connect 方法。
你可以使用任何由 UdpClient 所提供的发送方法把数据发送给远程设备。然后使用 Receive 方法来接收来自于远程主机的数据。
提示:如果你已经指定了一个默认的远程主机,就不要使用主机名称或者 IPEndPoint 来调用 Send 方法。如果你这样做,那么 UdpClient 将会抛出一个异常。

UdpClient 方法同样允许你发送和接收多点传送的数据包。而使用 JoinMulticastGroup 方法可以把 UdpClient 订阅到多点传送分组。也可以使用 DropMulticastGroup 方法把 UdpClient 从多点传送分组的订阅中取消。

本节介绍使用UdpClient实现一个同步的UDP服务器

UdpClient同步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.Sockets;  
  6. using System.Net;  
  7. using System.Threading;  
  8.   
  9. namespace NetFrame.Net.UDP.Listener.Synchronous  
  10. {  
  11.     /// <summary>  
  12.     /// UdpClient 实现同步UDP服务器  
  13.     /// </summary>  
  14.     public class UDPServer  
  15.     {  
  16.         #region Fields  
  17.         /// <summary>  
  18.         /// 服务器程序允许的最大客户端连接数  
  19.         /// </summary>  
  20.         private int _maxClient;  
  21.   
  22.         /// <summary>  
  23.         /// 当前的连接的客户端数  
  24.         /// </summary>  
  25.         //private int _clientCount;  
  26.   
  27.         /// <summary>  
  28.         /// 服务器使用的异步UdpClient  
  29.         /// </summary>  
  30.         private UdpClient _server;  
  31.   
  32.         /// <summary>  
  33.         /// 客户端会话列表  
  34.         /// </summary>  
  35.         //private List<UDPState> _clients;  
  36.   
  37.         private bool disposed = false;  
  38.   
  39.         /// <summary>  
  40.         /// 数据接受缓冲区  
  41.         /// </summary>  
  42.         private byte[] _recvBuffer;  
  43.  
  44.         #endregion  
  45.  
  46.         #region Properties  
  47.   
  48.         /// <summary>  
  49.         /// 服务器是否正在运行  
  50.         /// </summary>  
  51.         public bool IsRunning { getprivate set; }  
  52.         /// <summary>  
  53.         /// 监听的IP地址  
  54.         /// </summary>  
  55.         public IPAddress Address { getprivate set; }  
  56.         /// <summary>  
  57.         /// 监听的端口  
  58.         /// </summary>  
  59.         public int Port { getprivate set; }  
  60.         /// <summary>  
  61.         /// 通信使用的编码  
  62.         /// </summary>  
  63.         public Encoding Encoding { getset; }  
  64.  
  65.         #endregion  
  66.  
  67.         #region 构造函数  
  68.   
  69.         /// <summary>  
  70.         /// 同步UdpClient UDP服务器  
  71.         /// </summary>  
  72.         /// <param name="listenPort">监听的端口</param>  
  73.         public UDPServer(int listenPort)  
  74.             : this(IPAddress.Any, listenPort,1024)  
  75.         {  
  76.         }  
  77.   
  78.         /// <summary>  
  79.         /// 同步UdpClient UDP服务器  
  80.         /// </summary>  
  81.         /// <param name="localEP">监听的终结点</param>  
  82.         public UDPServer(IPEndPoint localEP)  
  83.             : this(localEP.Address, localEP.Port,1024)  
  84.         {  
  85.         }  
  86.   
  87.         /// <summary>  
  88.         /// 同步UdpClient UDP服务器  
  89.         /// </summary>  
  90.         /// <param name="localIPAddress">监听的IP地址</param>  
  91.         /// <param name="listenPort">监听的端口</param>  
  92.         /// <param name="maxClient">最大客户端数量</param>  
  93.         public UDPServer(IPAddress localIPAddress, int listenPort, int maxClient)  
  94.         {  
  95.             this.Address = localIPAddress;  
  96.             this.Port = listenPort;  
  97.             this.Encoding = Encoding.Default;  
  98.   
  99.             _maxClient = maxClient;  
  100.             //_clients = new List<AsyncUDPSocketState>();  
  101.             _server = new UdpClient(new IPEndPoint(this.Address, this.Port));  
  102.   
  103.             _recvBuffer=new byte[_server.Client.ReceiveBufferSize];  
  104.         }  
  105.  
  106.         #endregion  
  107.  
  108.         #region Method  
  109.         /// <summary>  
  110.         /// 启动服务器  
  111.         /// </summary>  
  112.         /// <returns>异步TCP服务器</returns>  
  113.         public void Start()  
  114.         {  
  115.             if (!IsRunning)  
  116.             {  
  117.                 IsRunning = true;  
  118.                 _server.EnableBroadcast = true;  
  119.                 new Thread(ReceiveData).Start();  
  120.             }  
  121.         }  
  122.   
  123.         /// <summary>  
  124.         /// 停止服务器  
  125.         /// </summary>  
  126.         public void Stop()  
  127.         {  
  128.             if (IsRunning)  
  129.             {  
  130.                 IsRunning = false;  
  131.                 _server.Close();  
  132.                 //TODO 关闭对所有客户端的连接  
  133.   
  134.             }  
  135.         }  
  136.   
  137.         /// <summary>  
  138.         /// 同步接收数据的方法  
  139.         /// </summary>  
  140.         /// <param name="ar"></param>  
  141.         private void ReceiveData()  
  142.         {  
  143.             IPEndPoint remote = null;  
  144.             while (true)  
  145.             {  
  146.                 byte[] buffer = null;  
  147.                 try  
  148.                 {  
  149.                     buffer = _server.Receive(ref remote);  
  150.                 }  
  151.                 catch (Exception)  
  152.                 {  
  153.                     //异常处理操作  
  154.                     return;  
  155.                 }  
  156.                 if (buffer == null || buffer.Length == 0) return;  
  157.                 //TODO 数据包收到触发事件  
  158.                 RaiseDataReceived(null);  
  159.             }  
  160.         }  
  161.   
  162.         /// <summary>  
  163.         /// 同步发送数据  
  164.         /// </summary>  
  165.         /// <param name="msg"></param>  
  166.         /// <param name="remote"></param>  
  167.         public void Send(string msg, IPEndPoint remote)  
  168.         {  
  169.             byte[] data = Encoding.Default.GetBytes(msg);  
  170.             try  
  171.             {  
  172.                 _server.Send(data, data.Length, remote);  
  173.             }  
  174.             catch (Exception)  
  175.             {  
  176.                 //TODO 异常处理  
  177.                 RaiseOtherException(null);  
  178.             }  
  179.         }  
  180.  
  181.         #endregion  
  182.  
  183.         #region 事件  
  184.         /// <summary>  
  185.         /// 接收到数据事件  
  186.         /// </summary>  
  187.         public event EventHandler<UDPEventArgs> DataReceived;  
  188.   
  189.         private void RaiseDataReceived(UDPState state)  
  190.         {  
  191.             if (DataReceived != null)  
  192.             {  
  193.                 DataReceived(thisnew UDPEventArgs(state));  
  194.             }  
  195.         }  
  196.   
  197.         /// <summary>  
  198.         /// 数据发送完毕事件  
  199.         /// </summary>  
  200.         public event EventHandler<UDPEventArgs> CompletedSend;  
  201.   
  202.         /// <summary>  
  203.         /// 触发数据发送完毕的事件  
  204.         /// </summary>  
  205.         /// <param name="state"></param>  
  206.         private void RaiseCompletedSend(UDPState state)  
  207.         {  
  208.             if (CompletedSend != null)  
  209.             {  
  210.                 CompletedSend(thisnew UDPEventArgs(state));  
  211.             }  
  212.         }  
  213.   
  214.         /// <summary>  
  215.         /// 网络错误事件  
  216.         /// </summary>  
  217.         public event EventHandler<UDPEventArgs> NetError;  
  218.         /// <summary>  
  219.         /// 触发网络错误事件  
  220.         /// </summary>  
  221.         /// <param name="state"></param>  
  222.         private void RaiseNetError(UDPState state)  
  223.         {  
  224.             if (NetError != null)  
  225.             {  
  226.                 NetError(thisnew UDPEventArgs(state));  
  227.             }  
  228.         }  
  229.   
  230.         /// <summary>  
  231.         /// 异常事件  
  232.         /// </summary>  
  233.         public event EventHandler<UDPEventArgs> OtherException;  
  234.         /// <summary>  
  235.         /// 触发异常事件  
  236.         /// </summary>  
  237.         /// <param name="state"></param>  
  238.         private void RaiseOtherException(UDPState state, string descrip)  
  239.         {  
  240.             if (OtherException != null)  
  241.             {  
  242.                 OtherException(thisnew UDPEventArgs(descrip, state));  
  243.             }  
  244.         }  
  245.         private void RaiseOtherException(UDPState state)  
  246.         {  
  247.             RaiseOtherException(state, "");  
  248.         }  
  249.         #endregion  
  250.  
  251.         #region Close  
  252.         /// <summary>  
  253.         /// 关闭一个与客户端之间的会话  
  254.         /// </summary>  
  255.         /// <param name="state">需要关闭的客户端会话对象</param>  
  256.         public void Close(UDPState state)  
  257.         {  
  258.             if (state != null)  
  259.             {  
  260.                 //_clients.Remove(state);  
  261.                 //_clientCount--;  
  262.                 //TODO 触发关闭事件  
  263.             }  
  264.         }  
  265.         /// <summary>  
  266.         /// 关闭所有的客户端会话,与所有的客户端连接会断开  
  267.         /// </summary>  
  268.         public void CloseAllClient()  
  269.         {  
  270.             //foreach (AsyncUDPSocketState client in _clients)  
  271.             //{  
  272.             //    Close(client);  
  273.             //}  
  274.             //_clientCount = 0;  
  275.             //_clients.Clear();  
  276.         }  
  277.  
  278.         #endregion  
  279.  
  280.         #region 释放  
  281.         /// <summary>  
  282.         /// Performs application-defined tasks associated with freeing,   
  283.         /// releasing, or resetting unmanaged resources.  
  284.         /// </summary>  
  285.         public void Dispose()  
  286.         {  
  287.             Dispose(true);  
  288.             GC.SuppressFinalize(this);  
  289.         }  
  290.   
  291.         /// <summary>  
  292.         /// Releases unmanaged and - optionally - managed resources  
  293.         /// </summary>  
  294.         /// <param name="disposing"><c>true</c> to release   
  295.         /// both managed and unmanaged resources; <c>false</c>   
  296.         /// to release only unmanaged resources.</param>  
  297.         protected virtual void Dispose(bool disposing)  
  298.         {  
  299.             if (!this.disposed)  
  300.             {  
  301.                 if (disposing)  
  302.                 {  
  303.                     try  
  304.                     {  
  305.                         Stop();  
  306.                         if (_server != null)  
  307.                         {  
  308.                             _server = null;  
  309.                         }  
  310.                     }  
  311.                     catch (SocketException)  
  312.                     {  
  313.                         //TODO  
  314.                         RaiseOtherException(null);  
  315.                     }  
  316.                 }  
  317.                 disposed = true;  
  318.             }  
  319.         }  
  320.         #endregion  
  321.     }  
  322. }  

用户状态封装类

[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.UDP.Listener.Synchronous  
  9. {  
  10.     public class UDPState  
  11.     {  
  12.         // Client   socket.  
  13.         public UdpClient udpClient = 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 IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);  
  22.     }  
  23. }  
服务器事件参数类

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值