Java网络编程:UDP DatagramSocket

原文地址

DatagramSocket类是java通过UDP通信的途径。UDP仍位于IP层的上面。 你可以用DatagramSocket类发送和接收UDP数据包。

UDP 和TCP

UDP工作方式和TCP有点不同。当你通过TCP发送数据时,你先要创建连接。一旦TCP连接建立了,TCP会保证你的数据传递到对端,否则它将告诉你已发生的错误。

仅仅用UDP来发送数据包(datagrams)到网络间的某个IP地址。你不能保证数据会不会到达。你也不能保证UDP数据包到达接收方的指令。这意味着UDP比TCP有更少的协议开销(无完整检查流)。

当数据传输过程中不在乎数据包是否丢失时,UDP就比较适合这样的数据传输。比如,网上的电视信号的传输。你希望信号到达客户端时尽可能地接近直播。因此,如果丢失一两个画面,你一点都不在乎。你不希望直播延迟,值想确保所有的画面显示在客户端。你宁可跳过丢失的画面,希望一直看到最新的画面。

这种情况也会发生在网上摄像机直播节目中。谁会关心过去发生的什么,你只想显示当前的画面。你不希望比实际情况慢30s结束,只因为你想看到摄像机显示给观众的所有画面。这跟摄像机录像有点不同。从摄像机录制画面到磁盘,你不希望丢失一个画面。你可能还希望有点延迟,如果有重大的情况发生,就不需要倒回去检查画面。

通过DatagramSocket发送数据

通过Java的DatagramSocket类发送数据,首先需要创建DatagramPacket。如下:

[code lang=”java”]

buffer = new byte[65508];

InetAddress address = new DatagramPacket(buffer, buffer.length, address,9000);

[/code]

字节缓冲块(字节数组)就是UDP数据包中用来发送的数据。缓冲块上限长度为65508字节,是单一UDP数据包发送的最大的数据量。

数据包构造函数的长度就是缓存块中用于发送的数据的长度。所有多于最大容量的数据都会被忽略。

包含节点(例如服务器)地址的InetAddress实例携带节点(如服务器)的地址发送的UDP数据包。InetAddress类表示一个ip地址(网络地址)。getByName()方法返回带有一个InetAddress实例,该实例带有匹配主机名的ip地址。

端口参数是UDP端口服务器用来接收正在监听的数据。UDP端口和TCP端口是不一样的。一台电脑同时有不同的进程监听UDP和TCP 80端口。

为了发送数据包,你需要创建DatagramSocket来发送数据。如下:

[code lang=”java”]

DatagramSocketdatagramSocket = new DatagramSocket();

[/code]

调用send()方法发送数据,像这样:

[code lang=”java”]

datagramSocket.send(packet);

[/code]

完整示例:

[code lang=”java”]

DatagramSocketdatagramSocket = new DatagramSocket();

byte[] buffer = "0123456789".getBytes();

InetAddressreceiverAddress = InetAddress.getLocalHost();

DataframPacket packet = new DatagramPacket( buffer, buffer.length, receiverAddress,80);
datagramSocket.send(packet);

[/code]

从DatagramSocket获取数据

从DataframSocket获取数据时,首先创建DataframPacket ,然后通过DatagramSocket类的receive()方法接收数据。例如:

[code lang=”java”]

DatagramSocketdatagramSocket = new DatagramSocket(80);

byte[] buffer = new byte[10];

DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

datagramSocket.receive(packet);

[/code]

注意DatagramSocket是如何通过传递参数80到它的构造器初始化的。这个参数是UDP端口的DatagramSocket用来接收UDP数据包的。像之前提到的,TCP和UDP端口是不一样的,也不重叠。你可以有俩个不同的进程同时在端口80监听TCP和UDP,没有任何冲突。

第二,字节缓存块和DatagramPacket创建了。注意DatagramPacket是没有关于节点如何发送数据的信息的,当创建一个方数据的DatagramPacket时,它会直到这个信息。这就是为什么我们会用DatagramPacket接收数据而不是发送数据。因此没有目标地址是必须的。

最后,调用DatagramSocket的receive()方法。直到数据包接收到为止,这个方法都是阻塞的。

接收的数据位于DatagramPacket的字节缓冲块。缓冲块可以通过调用getData()获得:

[code lang=”java”]

byte[] buffer = packet.getData();

[/code]

缓冲块接收了多少的数据需要你去找出来。你用的协议应该定义每个UDP包发多少数据,活着定义一个你能找到的数据结束标记。
一个真正的服务端程序可能会在一个loop中调用receive()方法,传送所有接收到的DatagramPacket到工作的线程池中,就像TCP服务器处理请求连接一样(查看Java Multithreaded Servers获取更多详情)

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java网络编程:UDP DatagramSocket

  • 11,641 人阅读
  • 2 条评论
  • Trackback 关闭
  • 评论 (2)
    • Tyrian
    • 2016/05/02 11:17上午

    这一段翻译的有点问题吧“UDP工作方式和TCP有点不同。当你通过TCP发送数据时,你先要创建连接。你不能保证数据会不会到达。你也不能保证UDP数据包到达接收方的指令。这意味着UDP比TCP有更少的协议开销(无完整检查流)。”

    原文应该是有两段的。

      • 司余
      • 2016/05/02 1:32下午

      非常感谢你的提醒。已经修改了。

return top