当前位置: 首页 > news >正文 UDP数据传输实例 news 来源:原创 2024/5/18 14:06:23 下面通过一个例子,对UdpClient类的用法及它的一些方法进行说明。在UDP模式下,不存在明显的服务器与客户端之分,所以在这里用A端和B端代替。本例要实现的功能是从A端到B端的点对点通信。打开VS2008,在D:C#ch17目录下建立名为P2PTest的Windows应用程序。打开工程,为当前窗体添加如表17-9所示控件。 表17-9 添加控件列表 控件名 Name Text Label Label1 对方IP: TextBox tbIP TextBox tbMsg Button btnSend 发送 ListBox lbInfo GroupBox gbSend 发送窗口 GroupBox gbReceive 接收窗口 Button btnClear 清空 本例是利用8888端口进行局域网内部的点对点通信,只要确认对方IP,就能相互发送信息。代码的添加主要分为以下步骤。 (1)首先是对几个命名空间的引用,包括System.Net、System.Net.Sockets和System.Threading。然后定义如下三个全局变量。 private UdpClient uc; private IPEndPoint iep; private Thread th; 其中UdpClient是本例的核心成员,主要通过它的相关方法进行数据的收发。 (2)本例使用8888端口进行通信,所以应该在当前窗体构造函数Form1()内,用该端口实例化UdpClient。 public Form1() { InitializeComponent(); CheckForIllegalCrossThreadCalls = false; uc = new UdpClient(8888); } CheckForIllegalCrossThreadCalls主要是解决线程间的控件操作问题,通过将其属性设置为fasle,可以禁用对操作控件的线程是否为创建该窗体的线程的检测,阻止该异常的发生。这种问题在第16章中也遇到过,当时是采用的委托的方法进行解决。 (3)双击“发送”按钮,添加如下代码。 iep = new IPEndPoint(IPAddress.Parse(tbIP.Text), 8888); th = new Thread(new ThreadStart(listen)); th.IsBackground = true; //设置在后台运行 th.Start(); //启动线程 string temp = tbMsg.Text; byte[] b = Encoding.UTF8.GetBytes(temp); //对发送的数据的进行UTF8格式的编码 uc.Send(b, b.Length,iep); //发送数据 其中listen()方法用于监听对方发送过来的消息,实现代码如下。 private void listen() { while (true) { string text = Encoding.UTF8.GetString(uc.Receive(ref iep)); //对发送的数据的进行UTF8格式的编码 lbInfo.Items.Add(text + "n"); } } (4)双击“清空”按钮,添加如下代码。 lbInfo.Items.Clear(); (5)最后还需要进行一些资源释放的操作。 protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); th.Abort(); //关闭线程 uc.Close(); //关闭UdpClient } base.Dispose(disposing); } 完成以上操作后,将该软件放在两台计算机之间进行测试。 在测试过程中,发送的数据有时不能被对方收到。这是UDP本身的特性造成的,因为UDP是不可靠的传输协议,这也是基于UDP通信的缺点之一。 在上面的例子中,收发数据用到了UdpClient类的几种方法,如Send()和Receive(),下面对这些方法进行详细说明。 首先看发送数据用到的Send()方法,它具有以下重载形式。 public int Send(byte[] dgram,int bytes); public int Send(byte[] dgram,int bytes,string hostname,int port); public int Send(byte[] dgram,int bytes); 其中,dgram表示需要发送的数据,它必须满足字节数组的格式;bytes表示该字节数组的长度;hostname和port指需要接收数据的主机名和端口号。 接着是接收数据用到的Receive()方法,它没有重载形式,声明如下。 public byte[] Receive(ref IPEndPoint remoteEP); 这里需要注意的是它的参数是引用类型,且remoteEP应该取发送方的IP和端口号。 JoinMulticastGroup()方法能将UdpClient类添加到多路广播组,它的用法如下所示。 public void JoinMulticastGroup(IPAddress multicastAddr); public void JoinMulticastGroup(IPAddress multicastAddr,int timeToLive); public void JoinMulticastGroup(int ifindex,IPAddress multicastAddr); multicastAddr和前面所提到的IPAddress的实例有了本质区别,它不再是单个主机的IP地址,而是一个广播地址。如果将IP中标识主机的部分全置“1”,即表示该网络的广播地址。比如校园网常用的C类地址,只要将最后8位全部置“1”即可得到本地网络中的广播地址。它的优势是能实现广播的功能,比如从A端发出数据,在B、C、D、E端等都能同时接收,而不是像上个例子中必须指定接收方的IP。timeToLive是按路由器跳数测量的TTL。 JoinMulticastGroup()的用法比较简单,如下所示。 using System.Net; using System.Net.Sockets; …… UdpClient uc = new UdpClient(); IPAddress bcip =IPAddress.Parse("222.18.142.255"); //C类IP的广播地址 try { uc.JoinMulticastGroup(bcip,20); //添加到多路组播 } catch(Exception ex) { Console.WriteLine(ex.Message); } DropMulticastGroup()方法进行与JoinMulticastGroup()方法相反的操作,用法如下所示。 public void DropMulticastGroup (IPAddress multicastAddr); 本节到目前为止,主要介绍了UdpClient类的用法,其实直接用Socket类也能完成同样的功能。鉴于篇幅有限,就不再详述。只是有一点需要指出,利用Socket连接创建基于UDP的通信时,它的实例化方法应与TCP进行区别,如下所示。 Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); 后面两个参数发生了变化,SocketType的类型选择Dgram,表示数据传输是以数据报的形式而非流;协议类型需要选择Udp。 UDP与TCP相比,在某些方面较有优势。比如它的实时性比TCP要好,它不需握手、差错检验和流的控制;它产生的负载很少等。它的缺点是数据传输不可靠。 相关文章: 在线播放器代码大全 TcpListener和TcpClient简单例子 C#自定义事件 socket传文件 c# 文件传输 SQL SERVER 2005分页查询语句 测试mssql中sql语句执行时间 SQL SERVER查询时间条件式写法 C#完整的通信代码(一)(点对点,点对多,同步,异步,UDP,TCP) C#完整的通信代码(二)(点对点,点对多,同步,异步,UDP,TCP) C# byte数组常用扩展 八种情况 C# Stream 和 byte[] 之间的转换 常用SQL/oracle循环语句 ORACLE 字符串操作 jquery下json数组的操作用法实例 【MySQL经典案例分析】 Waiting for table metadata lock 【知识碎片】第三方登录弹窗效果 Angular 响应式表单 基础例子 HTTP那些事 java概述 Java-详解HashMap js算法-归并排序(merge_sort) laravel 用artisan创建自己的模板 Shadow DOM 内部构造及如何构建独立组件 Spring思维导图,让Spring不再难懂(mvc篇) text-decoration与color属性 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法 盘点那些不知名却常用的 Git 操作 前端相关框架总和 如何正确配置 Ubuntu 14.04 服务器? 使用agvtool更改app version/build 提醒我喝水chrome插件开发指南 为视图添加丝滑的水波纹 小试R空间处理新库sf 一套莫尔斯电报听写、翻译系统 在 Chrome DevTools 中调试 JavaScript 入门 1.Ext JS 建立web开发工程 Spring第一个helloWorld 阿里云服务器如何修改远程端口? 基于django的视频点播网站开发-step3-注册登录功能 ... 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ... 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ... Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别 io --- 处理流的核心工具 马来语翻译中文去哪比较好? # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好 #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval() (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理 (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer (编译到47%失败)to be deleted (附源码)springboot学生选课系统 毕业设计 612555 (附源码)计算机毕业设计SSM疫情社区管理系统 (九)信息融合方式简介 (六) ES6 新特性 —— 迭代器(iterator) (学习日记)2024.03.12:UCOSIII第十四节:时基列表
下面通过一个例子,对UdpClient类的用法及它的一些方法进行说明。在UDP模式下,不存在明显的服务器与客户端之分,所以在这里用A端和B端代替。本例要实现的功能是从A端到B端的点对点通信。打开VS2008,在D:C#ch17目录下建立名为P2PTest的Windows应用程序。打开工程,为当前窗体添加如表17-9所示控件。 表17-9 添加控件列表 控件名 Name Text Label Label1 对方IP: TextBox tbIP TextBox tbMsg Button btnSend 发送 ListBox lbInfo GroupBox gbSend 发送窗口 GroupBox gbReceive 接收窗口 Button btnClear 清空 本例是利用8888端口进行局域网内部的点对点通信,只要确认对方IP,就能相互发送信息。代码的添加主要分为以下步骤。 (1)首先是对几个命名空间的引用,包括System.Net、System.Net.Sockets和System.Threading。然后定义如下三个全局变量。 private UdpClient uc; private IPEndPoint iep; private Thread th; 其中UdpClient是本例的核心成员,主要通过它的相关方法进行数据的收发。 (2)本例使用8888端口进行通信,所以应该在当前窗体构造函数Form1()内,用该端口实例化UdpClient。 public Form1() { InitializeComponent(); CheckForIllegalCrossThreadCalls = false; uc = new UdpClient(8888); } CheckForIllegalCrossThreadCalls主要是解决线程间的控件操作问题,通过将其属性设置为fasle,可以禁用对操作控件的线程是否为创建该窗体的线程的检测,阻止该异常的发生。这种问题在第16章中也遇到过,当时是采用的委托的方法进行解决。 (3)双击“发送”按钮,添加如下代码。 iep = new IPEndPoint(IPAddress.Parse(tbIP.Text), 8888); th = new Thread(new ThreadStart(listen)); th.IsBackground = true; //设置在后台运行 th.Start(); //启动线程 string temp = tbMsg.Text; byte[] b = Encoding.UTF8.GetBytes(temp); //对发送的数据的进行UTF8格式的编码 uc.Send(b, b.Length,iep); //发送数据 其中listen()方法用于监听对方发送过来的消息,实现代码如下。 private void listen() { while (true) { string text = Encoding.UTF8.GetString(uc.Receive(ref iep)); //对发送的数据的进行UTF8格式的编码 lbInfo.Items.Add(text + "n"); } } (4)双击“清空”按钮,添加如下代码。 lbInfo.Items.Clear(); (5)最后还需要进行一些资源释放的操作。 protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); th.Abort(); //关闭线程 uc.Close(); //关闭UdpClient } base.Dispose(disposing); } 完成以上操作后,将该软件放在两台计算机之间进行测试。 在测试过程中,发送的数据有时不能被对方收到。这是UDP本身的特性造成的,因为UDP是不可靠的传输协议,这也是基于UDP通信的缺点之一。 在上面的例子中,收发数据用到了UdpClient类的几种方法,如Send()和Receive(),下面对这些方法进行详细说明。 首先看发送数据用到的Send()方法,它具有以下重载形式。 public int Send(byte[] dgram,int bytes); public int Send(byte[] dgram,int bytes,string hostname,int port); public int Send(byte[] dgram,int bytes); 其中,dgram表示需要发送的数据,它必须满足字节数组的格式;bytes表示该字节数组的长度;hostname和port指需要接收数据的主机名和端口号。 接着是接收数据用到的Receive()方法,它没有重载形式,声明如下。 public byte[] Receive(ref IPEndPoint remoteEP); 这里需要注意的是它的参数是引用类型,且remoteEP应该取发送方的IP和端口号。 JoinMulticastGroup()方法能将UdpClient类添加到多路广播组,它的用法如下所示。 public void JoinMulticastGroup(IPAddress multicastAddr); public void JoinMulticastGroup(IPAddress multicastAddr,int timeToLive); public void JoinMulticastGroup(int ifindex,IPAddress multicastAddr); multicastAddr和前面所提到的IPAddress的实例有了本质区别,它不再是单个主机的IP地址,而是一个广播地址。如果将IP中标识主机的部分全置“1”,即表示该网络的广播地址。比如校园网常用的C类地址,只要将最后8位全部置“1”即可得到本地网络中的广播地址。它的优势是能实现广播的功能,比如从A端发出数据,在B、C、D、E端等都能同时接收,而不是像上个例子中必须指定接收方的IP。timeToLive是按路由器跳数测量的TTL。 JoinMulticastGroup()的用法比较简单,如下所示。 using System.Net; using System.Net.Sockets; …… UdpClient uc = new UdpClient(); IPAddress bcip =IPAddress.Parse("222.18.142.255"); //C类IP的广播地址 try { uc.JoinMulticastGroup(bcip,20); //添加到多路组播 } catch(Exception ex) { Console.WriteLine(ex.Message); } DropMulticastGroup()方法进行与JoinMulticastGroup()方法相反的操作,用法如下所示。 public void DropMulticastGroup (IPAddress multicastAddr); 本节到目前为止,主要介绍了UdpClient类的用法,其实直接用Socket类也能完成同样的功能。鉴于篇幅有限,就不再详述。只是有一点需要指出,利用Socket连接创建基于UDP的通信时,它的实例化方法应与TCP进行区别,如下所示。 Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); 后面两个参数发生了变化,SocketType的类型选择Dgram,表示数据传输是以数据报的形式而非流;协议类型需要选择Udp。 UDP与TCP相比,在某些方面较有优势。比如它的实时性比TCP要好,它不需握手、差错检验和流的控制;它产生的负载很少等。它的缺点是数据传输不可靠。