关于冰盾 | 使用条款 | 网站地图
 
使用UDP套接字发送和接收信息
使用UDP套接字发送和接收信息
作者:冰盾防火墙 网站:www.bingdun.com 日期:2015-02-12
 

本节我们将比较使用UDP套接字和TCP套接字进行通信的一些不同点。一个微小但重要的差别是UDP协议保留了消息的边界信息。DatagramSocket的每一次receive()调用最多只能接收调用一次send()方法所发送的数据。而且,不同的receive()方法调用绝不会返回同一个send()方法调用所发送的数据。

当在TCP套接字的输出流上调用的write()方法返回后,所有的调用者都知道数据已经被复制到一个传输缓存区中,实际上此时数据可能已经被传送,也可能还没有被传送(第6章中将对此进行详细介绍)。而UDP协议没有提供从网络错误中恢复的机制,因此,并不对可能需要重传的数据进行缓存。这就意味着,当send()方法调用返回时,消息已经被发送到了底层的传输信道中,并正处在(或即将处在)发送途中。

消息从网络到达后,其所包含数据被read()方法或receive()方法返回前,数据存储在一个先进先出(first-in, first-out,FIFO)的接收数据队列中。对于已连接的TCP套接字来说,所有已接收但还未传送的字节都看作是一个连续的字节序列(见第6章)。然而,对于UDP套接字来说,接收到的数据可能来自于不同的发送者。一个UDP套接字所接收的数据存放在一个消息队列中,每个消息都关联了其源地址信息。每次receive()调用只返回一条消息。然而,如果receive()方法在一个缓存区大小为n的DatagramPacket实例中调用,而接收队列中的第一条消息长度大于n,则receive()方法只返回这条消息的前n个字节。超出部分的其他字节都将自动被丢弃,而且对接收程序也没有任何消息丢失的提示!

出于这个原因,接收者应该提供一个有足够大的缓存空间的DatagramPacket实例,以完整地存放调用receive()方法时应用程序协议所允许的最大长度的消息。这个技术能够保证数据不会丢失。一个DatagramPacket实例中所运行传输的最大数据量为65507字节,即UDP数据报文所能负载的最多数据。因此,使用一个有65600字节左右缓存数组的数据包总是安全的。

同时,还需要记住的重要一点是,每一个DatagramPacket实例都包含一个内部消息长度值,而该实例一接收到新消息,这个长度值都可能改变(以反映实际接收的消息的字节数)。如果一个应用程序使用同一个DatagramPacket实例多次调用receive()方法,每次调用前就必须显式地将消息的内部长度重置为缓存区的实际长度。

对于新手的另一个潜在的问题根源是DatagramPacket类的getData()方法,该方法总是返回缓冲区的原始大小,忽略了实际数据的内部偏移量和长度信息。消息接收到DatagramPacket的缓存区时,只是修改了存放消息数据的地址。例如,假设buf是一个长度为20的字节数组,其在初始化时已使每个字节中存放了该字节在数组中的索引:

 

同时假设dg是一个DatagramPacket实例,我们将dg的缓存区设置为buf数组的中间10 个字节:

dg.setData(buf,5,10);

现在假设dgsocket是一个DatagramSocket实例,某人向dgsocket发送了一个包含以下内容的8字节的消息,

 

该消息接收到了dg中:

dgsocket.receive(dg);

此时,调用dg.getData()方法将返回buf字节数组的原始引用,其内容变为:

 
 可以看到buf数组中只有索引为5-12的字节被修改,一般而言,应用程序需要使用getOffset()和getData()方法来访问刚接收到的数据。一种可能的方式是将接收到的数据复制到一个单独的字节数组中,如下所示:
byte[] destBuf = new byte[dg.getLength()];
System.arraycopy(dg.getData(), dg.getOffset(),
destBuf, 0, destBuf.length);
在Java1.6中我们可以使用Arrays.copyOfRange()方法,只需要一步就能方便地实现以上功能:
byte[] destBuf = Arrays.copyOfRange(dg.getData(),dg.getOffset(),
dg.getOffset()+dg.getLength());
我们不需要在UDPEchoServer.java中执行复制操作,因为这个服务器根本不从DatagramPacket中读取数据。
【责任编辑:云霞 TEL:(010)68476606】

 

 
最新内容:
浅述传输层通信协议中的TCP和UDP[2015-02-12]
使用Java JDK中Java.net包控制UDP协议[2015-02-12]
UDP客户端框架[2015-02-12]
无连接的 UDP 协议[2015-02-12]
解析 Qt 网络之UDP 网络基础学习[2015-02-12]
TCP字节流与UDP数据报[2015-02-12]
相关内容:

合作伙伴: 黑基网 补天科技 威盾科技 站长下载 新飞金信 北京电信 ZOL应用下载
中华人民共和国增值电信业务经营许可证京ICP备14024464 公安备案号 京1081234 
版权所有©2003-2016 冰盾防火墙  www.BingDun.com 法律声明
服务热线:(010)51661195