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

本文主要是介绍C#网络编程系列文章(七)之UdpClient实现异步UDP服务器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原创性声明

本文作者:小竹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.   
  8. namespace NetFrame.Net.UDP.Listener.Asynchronous  
  9. {  
  10.     /// <summary>  
  11.     /// UdpClient 实现异步UDP服务器  
  12.     /// </summary>  
  13.     public class AsyncUDPServer  
  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.         /// 服务器使用的异步UdpClient  
  28.         /// </summary>  
  29.         private UdpClient _server;  
  30.   
  31.         /// <summary>  
  32.         /// 客户端会话列表  
  33.         /// </summary>  
  34.         //private List<AsyncUDPState> _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.         /// 异步UdpClient UDP服务器  
  70.         /// </summary>  
  71.         /// <param name="listenPort">监听的端口</param>  
  72.         public AsyncUDPServer(int listenPort)  
  73.             : this(IPAddress.Any, listenPort,1024)  
  74.         {  
  75.         }  
  76.   
  77.         /// <summary>  
  78.         /// 异步UdpClient UDP服务器  
  79.         /// </summary>  
  80.         /// <param name="localEP">监听的终结点</param>  
  81.         public AsyncUDPServer(IPEndPoint localEP)  
  82.             : this(localEP.Address, localEP.Port,1024)  
  83.         {  
  84.         }  
  85.   
  86.         /// <summary>  
  87.         /// 异步UdpClient UDP服务器  
  88.         /// </summary>  
  89.         /// <param name="localIPAddress">监听的IP地址</param>  
  90.         /// <param name="listenPort">监听的端口</param>  
  91.         /// <param name="maxClient">最大客户端数量</param>  
  92.         public AsyncUDPServer(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.             _server = new UdpClient(new IPEndPoint(this.Address, this.Port));  
  101.   
  102.             _recvBuffer=new byte[_server.Client.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.                 _server.EnableBroadcast = true;  
  118.                 _server.BeginReceive(ReceiveDataAsync, null);  
  119.             }  
  120.         }  
  121.   
  122.         /// <summary>  
  123.         /// 停止服务器  
  124.         /// </summary>  
  125.         public void Stop()  
  126.         {  
  127.             if (IsRunning)  
  128.             {  
  129.                 IsRunning = false;  
  130.                 _server.Close();  
  131.                 //TODO 关闭对所有客户端的连接  
  132.   
  133.             }  
  134.         }  
  135.   
  136.         /// <summary>  
  137.         /// 接收数据的方法  
  138.         /// </summary>  
  139.         /// <param name="ar"></param>  
  140.         private void ReceiveDataAsync(IAsyncResult ar)  
  141.         {  
  142.             IPEndPoint remote=null;  
  143.             byte[] buffer = null;  
  144.             try  
  145.             {  
  146.                 buffer = _server.EndReceive(ar, ref remote);  
  147.   
  148.                 //触发数据收到事件  
  149.                 RaiseDataReceived(null);  
  150.             }  
  151.             catch (Exception)  
  152.             {  
  153.                 //TODO 处理异常  
  154.                 RaiseOtherException(null);  
  155.             }  
  156.             finally  
  157.             {  
  158.                 if (IsRunning && _server != null)  
  159.                     _server.BeginReceive(ReceiveDataAsync, null);  
  160.             }  
  161.         }  
  162.   
  163.         /// <summary>  
  164.         /// 发送数据  
  165.         /// </summary>  
  166.         /// <param name="msg"></param>  
  167.         /// <param name="remote"></param>  
  168.         public void Send(string msg, IPEndPoint remote)  
  169.         {  
  170.             byte[] data = Encoding.Default.GetBytes(msg);  
  171.             try  
  172.             {  
  173.                 RaisePrepareSend(null);  
  174.                 _server.BeginSend(data, data.Length, new AsyncCallback(SendCallback), null);  
  175.             }  
  176.             catch (Exception)  
  177.             {  
  178.                 //TODO 异常处理  
  179.                 RaiseOtherException(null);  
  180.             }  
  181.         }  
  182.   
  183.         private void SendCallback(IAsyncResult ar)  
  184.         {  
  185.             if (ar.IsCompleted)  
  186.             {  
  187.                 try  
  188.                 {  
  189.                     _server.EndSend(ar);  
  190.                     //消息发送完毕事件  
  191.                     RaiseCompletedSend(null);  
  192.                 }  
  193.                 catch (Exception)  
  194.                 {  
  195.                     //TODO 数据发送失败事件  
  196.                     RaiseOtherException(null);  
  197.                 }  
  198.             }  
  199.   
  200.         }  
  201.         #endregion  
  202.  
  203.         #region 事件  
  204.         /// <summary>  
  205.         /// 接收到数据事件  
  206.         /// </summary>  
  207.         public event EventHandler<AsyncUDPEventArgs> DataReceived;  
  208.   
  209.         private void RaiseDataReceived(AsyncUDPState state)  
  210.         {  
  211.             if (DataReceived != null)  
  212.             {  
  213.                 DataReceived(thisnew AsyncUDPEventArgs(state));  
  214.             }  
  215.         }  
  216.   
  217.         /// <summary>  
  218.         /// 发送数据前的事件  
  219.         /// </summary>  
  220.         public event EventHandler<AsyncUDPEventArgs> PrepareSend;  
  221.   
  222.         /// <summary>  
  223.         /// 触发发送数据前的事件  
  224.         /// </summary>  
  225.         /// <param name="state"></param>  
  226.         private void RaisePrepareSend(AsyncUDPState state)  
  227.         {  
  228.             if (PrepareSend != null)  
  229.             {  
  230.                 PrepareSend(thisnew AsyncUDPEventArgs(state));  
  231.             }  
  232.         }  
  233.   
  234.         /// <summary>  
  235.         /// 数据发送完毕事件  
  236.         /// </summary>  
  237.         public event EventHandler<AsyncUDPEventArgs> CompletedSend;  
  238.   
  239.         /// <summary>  
  240.         /// 触发数据发送完毕的事件  
  241.         /// </summary>  
  242.         /// <param name="state"></param>  
  243.         private void RaiseCompletedSend(AsyncUDPState state)  
  244.         {  
  245.             if (CompletedSend != null)  
  246.             {  
  247.                 CompletedSend(thisnew AsyncUDPEventArgs(state));  
  248.             }  
  249.         }  
  250.   
  251.         /// <summary>  
  252.         /// 网络错误事件  
  253.         /// </summary>  
  254.         public event EventHandler<AsyncUDPEventArgs> NetError;  
  255.         /// <summary>  
  256.         /// 触发网络错误事件  
  257.         /// </summary>  
  258.         /// <param name="state"></param>  
  259.         private void RaiseNetError(AsyncUDPState state)  
  260.         {  
  261.             if (NetError != null)  
  262.             {  
  263.                 NetError(thisnew AsyncUDPEventArgs(state));  
  264.             }  
  265.         }  
  266.   
  267.         /// <summary>  
  268.         /// 异常事件  
  269.         /// </summary>  
  270.         public event EventHandler<AsyncUDPEventArgs> OtherException;  
  271.         /// <summary>  
  272.         /// 触发异常事件  
  273.         /// </summary>  
  274.         /// <param name="state"></param>  
  275.         private void RaiseOtherException(AsyncUDPState state, string descrip)  
  276.         {  
  277.             if (OtherException != null)  
  278.             {  
  279.                 OtherException(thisnew AsyncUDPEventArgs(descrip, state));  
  280.             }  
  281.         }  
  282.         private void RaiseOtherException(AsyncUDPState state)  
  283.         {  
  284.             RaiseOtherException(state, "");  
  285.         }  
  286.         #endregion  
  287.  
  288.         #region Close  
  289.         /// <summary>  
  290.         /// 关闭一个与客户端之间的会话  
  291.         /// </summary>  
  292.         /// <param name="state">需要关闭的客户端会话对象</param>  
  293.         public void Close(AsyncUDPState state)  
  294.         {  
  295.             if (state != null)  
  296.             {  
  297.                 //_clients.Remove(state);  
  298.                 //_clientCount--;  
  299.                 //TODO 触发关闭事件  
  300.             }  
  301.         }  
  302.         /// <summary>  
  303.         /// 关闭所有的客户端会话,与所有的客户端连接会断开  
  304.         /// </summary>  
  305.         public void CloseAllClient()  
  306.         {  
  307.             //foreach (AsyncUDPSocketState client in _clients)  
  308.             //{  
  309.             //    Close(client);  
  310.             //}  
  311.             //_clientCount = 0;  
  312.             //_clients.Clear();  
  313.         }  
  314.  
  315.         #endregion  
  316.  
  317.         #region 释放  
  318.         /// <summary>  
  319.         /// Performs application-defined tasks associated with freeing,   
  320.         /// releasing, or resetting unmanaged resources.  
  321.         /// </summary>  
  322.         public void Dispose()  
  323.         {  
  324.             Dispose(true);  
  325.             GC.SuppressFinalize(this);  
  326.         }  
  327.   
  328.         /// <summary>  
  329.         /// Releases unmanaged and - optionally - managed resources  
  330.         /// </summary>  
  331.         /// <param name="disposing"><c>true</c> to release   
  332.         /// both managed and unmanaged resources; <c>false</c>   
  333.         /// to release only unmanaged resources.</param>  
  334.         protected virtual void Dispose(bool disposing)  
  335.         {  
  336.             if (!this.disposed)  
  337.             {  
  338.                 if (disposing)  
  339.                 {  
  340.                     try  
  341.                     {  
  342.                         Stop();  
  343.                         if (_server != null)  
  344.                         {  
  345.                             _server = null;  
  346.                         }  
  347.                     }  
  348.                     catch (SocketException)  
  349.                     {  
  350.                         //TODO  
  351.                         RaiseOtherException(null);  
  352.                     }  
  353.                 }  
  354.                 disposed = true;  
  355.             }  
  356.         }  
  357.         #endregion  
  358.     }  
  359. }  

客户端信息封装了类

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

这篇关于C#网络编程系列文章(七)之UdpClient实现异步UDP服务器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/319928

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo