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。如下:
buffer = new byte[65508]; InetAddress address = new DatagramPacket(buffer, buffer.length, address,9000);
字节缓冲块(字节数组)就是UDP数据包中用来发送的数据。缓冲块上限长度为65508字节,是单一UDP数据包发送的最大的数据量。
数据包构造函数的长度就是缓存块中用于发送的数据的长度。所有多于最大容量的数据都会被忽略。
包含节点(例如服务器)地址的InetAddress实例携带节点(如服务器)的地址发送的UDP数据包。InetAddress类表示一个ip地址(网络地址)。getByName()方法返回带有一个InetAddress实例,该实例带有匹配主机名的ip地址。
端口参数是UDP端口服务器用来接收正在监听的数据。UDP端口和TCP端口是不一样的。一台电脑同时有不同的进程监听UDP和TCP 80端口。
为了发送数据包,你需要创建DatagramSocket来发送数据。如下:
DatagramSocketdatagramSocket = new DatagramSocket();
调用send()方法发送数据,像这样:
datagramSocket.send(packet);
完整示例:
DatagramSocketdatagramSocket = new DatagramSocket(); byte[] buffer = "0123456789".getBytes(); InetAddressreceiverAddress = InetAddress.getLocalHost(); DataframPacket packet = new DatagramPacket( buffer, buffer.length, receiverAddress,80); datagramSocket.send(packet);
从DatagramSocket获取数据
从DataframSocket获取数据时,首先创建DataframPacket ,然后通过DatagramSocket类的receive()方法接收数据。例如:
DatagramSocketdatagramSocket = new DatagramSocket(80); byte[] buffer = new byte[10]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); datagramSocket.receive(packet);
注意DatagramSocket是如何通过传递参数80到它的构造器初始化的。这个参数是UDP端口的DatagramSocket用来接收UDP数据包的。像之前提到的,TCP和UDP端口是不一样的,也不重叠。你可以有俩个不同的进程同时在端口80监听TCP和UDP,没有任何冲突。
第二,字节缓存块和DatagramPacket创建了。注意DatagramPacket是没有关于节点如何发送数据的信息的,当创建一个方数据的DatagramPacket时,它会直到这个信息。这就是为什么我们会用DatagramPacket接收数据而不是发送数据。因此没有目标地址是必须的。
最后,调用DatagramSocket的receive()方法。直到数据包接收到为止,这个方法都是阻塞的。
接收的数据位于DatagramPacket的字节缓冲块。缓冲块可以通过调用getData()获得:
byte[] buffer = packet.getData();
缓冲块接收了多少的数据需要你去找出来。你用的协议应该定义每个UDP包发多少数据,活着定义一个你能找到的数据结束标记。
一个真正的服务端程序可能会在一个loop中调用receive()方法,传送所有接收到的DatagramPacket到工作的线程池中,就像TCP服务器处理请求连接一样(查看Java Multithreaded Servers获取更多详情)
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/117240.html