1、1第十一章第十一章 UDP协议开发协议开发 11.1 UDP协议概述协议概述 11.2 UDP协议的套接字编程技术协议的套接字编程技术11.3 使用使用UdpClient简化简化UDP编程编程11.4 使用使用UDP协议进行广播和组播协议进行广播和组播11.5 小结小结211.1 UDP协议概述协议概述11.1.1 UDP协议的特点协议的特点l一个简单的、面向数据报的无连接协议一个简单的、面向数据报的无连接协议l提供了快速但不一定可靠的传输服务提供了快速但不一定可靠的传输服务l构建于底层构建于底层IP协议之上的传输层协议协议之上的传输层协议l不保证数据包一定到达目的,适用于可靠性较高不保证数据
2、包一定到达目的,适用于可靠性较高的局域网的局域网l可以使用广播的方式向子网上所有设备可以使用广播的方式向子网上所有设备 发送消息发送消息l可以使用组播的方式同时向网络上的多个设备发可以使用组播的方式同时向网络上的多个设备发送消息送消息 311.1.2 UDP与与TCP的比较的比较 l速度快:基于无连接的,消除连接的系统延迟速度快:基于无连接的,消除连接的系统延迟l一对多:支持一对多发送,一对多:支持一对多发送,TCP仅支持一对一仅支持一对一l占用网络带宽少:和占用网络带宽少:和TCP的报头比为的报头比为8:20l消息边界:消息边界:UDP有消息边界,有消息边界,TCP无无l可靠性:可靠性:UD
3、P可靠性差,无法保证消息传送到了可靠性差,无法保证消息传送到了目标目标l乱序性:网络非常拥挤时可能会出现乱序性:网络非常拥挤时可能会出现411.2 UDP协议的套接字编程技术协议的套接字编程技术11.2.1 使用使用SendTo和和ReceiveFrom方法方法11.2.2 使用使用Send和和Receive方法方法11.2.3 解决解决UDP数据丢失问题数据丢失问题511.2.1 使用使用SendTo和和ReceiveFrom方法方法1.1.编程思路编程思路 UDP UDP UDP Socket()Bind()ReceiveFrom()SendTo()Close()Socket()Bind(
4、)SendTo()ReceiveFrom()Close()611.2.1 使用使用SendTo和和ReceiveFrom方法方法(续续)2.编程步骤编程步骤1 创建套接字创建套接字 Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);2 如果要接收如果要接收UDP数据包,需要将创建的套接字数据包,需要将创建的套接字与本地与本地IPEndPoint进行绑定;进行绑定;3 使用使用SendTo方法和方法和ReceiveFrom方法发送和接收方法发送和接收数据包数据包711.2.1 使用使用SendTo和和Rece
5、iveFrom方法方法(续续)3.方法简介方法简介1 SendTo方法的几种重载形式方法的几种重载形式lpublic int SendTo(byte data,EndPoint remote)lpublic int SendTo(byte data,SocketFlags flags,EndPoint remote)lpublic int SendTo(byte data,int size,SocketFlags flags,EndPoint remote)lpublic int SendTo(byte data,int offset,int size,SocketFlags flags,En
6、dPoint remote)811.2.1 使用使用SendTo和和ReceiveFrom方法方法(续续)2 ReceiveFrom方法的几种重载形式方法的几种重载形式lpublic int ReceiveFrom(byte data,ref EndPoint remote)lpublic int ReceiveFrom(byte data,SocketFlags flags,ref EndPoint remote)lpublic int ReceiveFrom(byte data,int size,SocketFlags flags,ref EndPoint remote)lpublic i
7、nt ReceiveFrom(byte data,int offset,int size,SocketFlags flags,ref EndPoint remote)911.2.1 使用使用SendTo和和ReceiveFrom方法方法(续续)4.示例分析示例分析public static void Main()int length;byte bytes=new byte1024;Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);IPEndPoint myHost=new
8、 IPEndPoint(IPAddress.Any,6789);socket.Bind(myHost);IPEndPoint remote=new IPEndPoint(IPAddress.Parse(127.0.0.1),6789);EndPoint remoteHost=(EndPoint)remote;1011.2.1 使用使用SendTo和和ReceiveFrom方法方法(续续)Console.Write(输入发送的信息输入发送的信息:);string str=Console.ReadLine();bytes=System.Text.Encoding.Unicode.GetBytes(
9、str);socket.SendTo(bytes,bytes.Length,SocketFlags.None,remoteHost);while(true)Console.WriteLine(等待接收等待接收.);length=socket.ReceiveFrom(bytes,ref remoteHost);str=System.Text.Encoding.Unicode.GetString(bytes,0,length);Console.WriteLine(接收到信息:接收到信息:0,str);if(str=bye)break;1111.2.1 使用使用SendTo和和ReceiveFrom
10、方法方法(续续)Console.Write(输入回送信息(输入回送信息(bye退出退出):):);str=Console.ReadLine();bytes=System.Text.Encoding.Unicode.GetBytes(str);socket.SendTo(bytes,remoteHost);socket.Shutdown(SocketShutdown.Both);socket.Close();Console.WriteLine(对方已经对方已经byebye了,请按回车键结束了,请按回车键结束。);Console.ReadLine();12131411.2.1 使用使用SendTo
11、和和ReceiveFrom方法方法(续续)5.适用范围适用范围 使用使用SendTo和和ReceiveFrom方法传递数据时需方法传递数据时需要在参数中指定远程主机,比较适合向多个远程主要在参数中指定远程主机,比较适合向多个远程主机发送数据。机发送数据。1511.2.1 使用使用SendTo和和ReceiveFrom方法方法(续续)6.示例示例:关于关于receiveFrom中使用中使用 ref的的EndPoint 例例:RefEndPoint1617181911.2.2 使用使用Send和和Receive方法方法1.编程思路编程思路 UDP UDP Socket()Bind()Connect
12、()Receive()Send()Close()Socket()Bind()Connect()Send()Receive()Close()2011.2.2 使用使用Send和和Receive方法方法(续续)说明:说明:1 Bind()方法仅仅用于指明接收数据时本地方法仅仅用于指明接收数据时本地IP和端口号。和端口号。2 Connect()方法用于指明发送数据时接收方方法用于指明发送数据时接收方的的IP和端口号;接收数据的发送方的和端口号;接收数据的发送方的IP和端口和端口号。号。和和TCP中不一样中不一样 3 并没有实际的通信链路存在。并没有实际的通信链路存在。2111.2.2 使用使用Sen
13、d和和Receive方法方法(续续)2.编程步骤编程步骤1 创建套接字创建套接字 Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);2 用用Bind方法将创建的套接字与本地方法将创建的套接字与本地IPEndPoint进行绑定;进行绑定;(用于接收消息用于接收消息)3 用用Connect方法建立与远程主机联系方法建立与远程主机联系(用于确定用于确定远程主机的信息远程主机的信息);4 使用使用Send方法和方法和Receive方法发送和接收数据包方法发送和接收数据包2211.2.2 使用使用Send和和Rece
14、ive方法方法(续续)3.示例分析示例分析public static void Main()int length;byte bytes=new byte1024;Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);IPEndPoint myHost=new IPEndPoint(IPAddress.Any,6789);socket.Bind(myHost);IPEndPoint remote=new IPEndPoint(IPAddress.Parse(127.0.0.1,
15、6789);socket.Connect(remote);Console.Write(输入发送的信息:输入发送的信息:);string str=Console.ReadLine();bytes=System.Text.Encoding.Unicode.GetBytes(str);2311.2.2 使用使用Send和和Receive方法方法(续续)socket.Send(bytes);while(true)Console.WriteLine(等待接收等待接收.);length=socket.Receive(bytes);str=System.Text.Encoding.Unicode.GetSt
16、ring(bytes,0,length);Console.WriteLine(接收到信息:接收到信息:0,str);if(str=bye)break;Console.Write(输入回送信息(输入回送信息(bye退出退出):):);str=Console.ReadLine();bytes=System.Text.Encoding.Unicode.GetBytes(str);socket.Send(bytes);socket.Shutdown(SocketShutdown.Both);socket.Close();Console.WriteLine(对方已经对方已经byebye了,请按回车键结束
17、了,请按回车键结束。);Console.ReadLine();2411.2.2 使用使用Send和和Receive方法方法(续续)4.适用范围适用范围 仅对一台远程主机进行通信仅对一台远程主机进行通信2511.2.3 解决解决UDP数据丢失问题数据丢失问题1.UDP 数据丢失的原因数据丢失的原因lUDP通信没有缓冲机制,发送到网络的数据都是通信没有缓冲机制,发送到网络的数据都是立即发送的;因此容易引起数据的丢失现象立即发送的;因此容易引起数据的丢失现象l使用套接字接收数据时,还必须保证指定的字节使用套接字接收数据时,还必须保证指定的字节数组的容量足够大,如果太小也会引起数据丢失数组的容量足够大
18、,如果太小也会引起数据丢失2611.2.3 解决解决UDP数据丢失问题数据丢失问题(续续)2.解决方案解决方案 采用消息应答机制,采用消息应答机制,要求远程主机返回一个应答信息,要求远程主机返回一个应答信息,表明已经接收到发送的数据,如果在规定时间内没有收到表明已经接收到发送的数据,如果在规定时间内没有收到返回的应答信息,就认为该数据包已经丢失,然后重新发返回的应答信息,就认为该数据包已经丢失,然后重新发送刚才发送的数据包。送刚才发送的数据包。具体步骤如下:具体步骤如下:1)向远程主机发送一条消息。向远程主机发送一条消息。2)等待远程主机回送应答信息。等待远程主机回送应答信息。3)如果收到应答
19、信息,则退出本循环,继续发送下一如果收到应答信息,则退出本循环,继续发送下一条消息。如果在规定时间内没有收到应答信息,则重新发条消息。如果在规定时间内没有收到应答信息,则重新发送。送。4)检查重复发送次数,如果达到规定的重复次数,则检查重复发送次数,如果达到规定的重复次数,则终止发送,并显示相关错误信息。终止发送,并显示相关错误信息。2711.2.3 解决解决UDP数据丢失问题数据丢失问题(续续)3.示例分析示例分析public static void Main()bool exit=false;int length;byte bytes=new byte1024;Socket socket=
20、new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout,2000);IPEndPoint myHost=new IPEndPoint(IPAddress.Any,6789);socket.Bind(myHost);IPEndPoint iep=new IPEndPoint(IPAddress.Parse(127.0.0.1),6789);EndPo
21、int remote=(EndPoint)iep;2811.2.3 解决解决UDP数据丢失问题数据丢失问题(续续)while(true)int retry=0;while(true)try Console.Write(输入发送的信息(输入发送的信息(bye退出):退出):);string str=Console.ReadLine();if(str=bye)exit=true;break;bytes=System.Text.Encoding.Unicode.GetBytes(str);socket.SendTo(bytes,remote);socket.ReceiveFrom(bytes,ref
22、 remote);str=System.Text.Encoding.Unicode.GetString(bytes);Console.WriteLine(接收到信息:接收到信息:0,str);2911.2.3 解决解决UDP数据丢失问题数据丢失问题(续续)catch if(retry 使用使用MulticastOption类定义组播组,使用类定义组播组,使用SetSocketOption方法增加套接字到组播组方法增加套接字到组播组socket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.AddMembership,new Mult
23、icastOption(address);2 设置组播的设置组播的TTL值,该值允许路由器进行多少值,该值允许路由器进行多少次转发,默认值为次转发,默认值为1,只能在本子网发送。,只能在本子网发送。socket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.MulticastTimeLive,50)11.4.3 组播编程实例分析组播编程实例分析512.使用使用 UdpClient组播组播 1发送方发送方static void Main()UdpClient uc=new UdpClient();IPEndPoint iep=new
24、IPEndPoint(IPAddress.Parse(224.100.0.1),6788);byte bytes=System.Text.Encoding.Unicode.GetBytes(This is a test Message);uc.Send(bytes,bytes.Length,iep);uc.Close();522 接受方接受方public static void Main()UdpClient uc=new UdpClient(6788);uc.JoinMulticastGroup(IPAddress.Parse(224.100.0.1),50);IPEndPoint iep=
25、new IPEndPoint(IPAddress.Any,0);byte bytes=uc.Receive(ref iep);string str=System.Text.Encoding.Unicode.GetString(bytes,0,bytes.Length);Console.WriteLine(str);uc.Close();53程序界面如图:程序界面如图:11.4.4 网络会议网络会议 5411.5 小结小结 11.5.1 UDP协议的特点协议的特点l无连接协议无连接协议l快速快速l传输层协议传输层协议l可靠性较差可靠性较差l广播广播l组播组播5511.5.2 UDP协议的套接字编
26、程技术协议的套接字编程技术1.使用使用SendTo和和ReceiveFrom方法方法 UDP UDP Socket()Bind()ReceiveFrom()SendTo()Close()Socket()Bind()SendTo()ReceiveFrom()Close()5611.5.2 UDP协议的套接字编程技术协议的套接字编程技术2.使用使用Send和和Receive方法方法 UDP UDP Socket()Bind()Connect()Receive()Send()Close()Socket()Bind()Connect()Send()Receive()Close()5711.5.3 解决
27、解决UDP数据丢失问题数据丢失问题1.UDP 数据丢失的原因数据丢失的原因lUDP通信没有缓冲机制通信没有缓冲机制l使用套接字接收数据时,还必须保证指定的字节使用套接字接收数据时,还必须保证指定的字节数组的容量足够大,如果太小也会引起数据丢失数组的容量足够大,如果太小也会引起数据丢失2.解决方案解决方案 采用消息应答机制采用消息应答机制l接收信息超时处理接收信息超时处理l异常处理异常处理 5811.5.4 UdpClient简化简化UDP编程编程 UdpClient类简化了类简化了UDP套接字编程,该类提套接字编程,该类提供了一些简单的方法,用于在阻塞同步模式下发送供了一些简单的方法,用于在阻
28、塞同步模式下发送和接收无连接和接收无连接UDP数据报。数据报。5911.5.5 广播与组播广播与组播 1.几个概念几个概念广播:向子网中所有设备发送消息广播:向子网中所有设备发送消息 本地广播:向同一子网中所有设备发送消息本地广播:向同一子网中所有设备发送消息 全球广播:全球广播:Internet上所有设备发送消息上所有设备发送消息组播:向不同的子网内选择的设备子集发送消息组播:向不同的子网内选择的设备子集发送消息6011.5.5 广播与组播广播与组播(续续)2.广播地址广播地址 本地广播地址:本地广播地址:IP:192.168.0.0 子网掩码:子网掩码:255.255.0.0广播地址:广播
29、地址:192.168.255.255 IP:192.168.0.0 子网掩码:子网掩码:255.255.255.0广播地址:广播地址:192.168.0.255 全球广播地址全球广播地址:255.255.255.2556111.5.5 广播与组播广播与组播(续续)3.组播地址组播地址 D类地址:类地址:224.x.x.x239.x.x.x组播地址的分类:组播地址的分类:保留:保留:224.0.0.0-224.0.0.255 用户组播地址:用户组播地址:224.0.1.0-238.255.255.255 本地管理组:本地管理组:239.0.0.0-239.255.255.255(用于私人组(用于
30、私人组播领域,类似私有播领域,类似私有IP地址)地址)补充:补充:私有地址(私有地址(Private address)属于非注册地址,专门为)属于非注册地址,专门为组织机构内部使用。以下列出留用的内部私有地址组织机构内部使用。以下列出留用的内部私有地址A类类 10.0.0.0-10.255.255.255B类类 172.16.0.0-172.31.255.255C类类 192.168.0.0-192.168.255.255 6211.5.5 广播与组播广播与组播(续续)4.广播编程技术广播编程技术 发发送端送端:1 找出本地子网找出本地子网IP广播地址广播地址 2 允许套接字发送广播消息允许套
31、接字发送广播消息 socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.Broadcast,1);3 SendTo 发送信息发送信息 接收端:接收端:1 Bind本地本地IP和端口地址和端口地址 2 ReceiveFrom 接收信息接收信息(IPAddress.Any)6311.5.5 广播与组播广播与组播(续续)5.组播编程技术组播编程技术Socket类类 1 使用使用MulticastOption类定义组播组,使用类定义组播组,使用SetSocketOption方法增加套接字到组播组方法增加套接字到组播组 socket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.AddMembership,new MulticastOption(address);2 设置组播的设置组播的TTL值,该值允许路由器进行多少次转值,该值允许路由器进行多少次转发,默认值为发,默认值为1,只能在本子网发送。,只能在本子网发送。socket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.MulticastTimeLive,50)6.使用使用 UdpClient组播组播