Java UDP通信:DatagramSocket和DatagramPacket
来源:互联网 发布:网络黄金是什么 编辑:程序博客网 时间:2024/06/07 02:51
UDP 是在IP网络上收发数据的传输层协议,其速度快但不可靠。为什么会使用这种不可靠的协议呢?许多应用保持最快的速度比保证每一位数据都正确更为重要,例如实时音频或视频丢失数据只会作为干扰出现并且可以容忍;另外一些应用,利用UDP数据传输可靠性就需要在应用中进行控制。DNS、NFS、TFTP等都可以配置使用UDP协议。
我们都知道TCP是面向连接的,所谓连接就是在端点通信前建立起一条“虚电路”,利用逻辑标识来控制路由寻路,这个逻辑标识记录了目的IP、端口、虚电路标识等信息。UDP是无需连接,每个传输单元就称为数据包,数据包上就记录了相应的路由信息,且前后传输的数据包可不相关,这就要求各数据包中记录路由信息。而TCP建立好虚电路后,每个传输单元是不需要关心这些信息的。面向连接的TCP有诸多优点,如可靠性、拥塞可控等,但是其仅能用于端点间通信而不能用于广播或者组播通信,后两者还需要UDP发挥作用。
Java用两个类实现UDP:DatagramPacket和DatagramSocket,前者将数据字节填充到UDP包,后者收发UDP包。用法很简单,DatagramSocket收发DatagramPacket即可。与TCP不同,UDP的socket并没有客户端和服务端的区别而统一应用此对象。下面给出利用UDP单播通信的daytime示意:
UDPServer.java
daytime服务端
import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;import java.net.SocketTimeoutException;import java.util.Date;/** * Created by Cheney Hwang on 2017/5/9. */public class UDPServer { public final static int PORT = 5555; public static void main(String[] args) { byte[] buffer = new byte[64]; //侦听某个UDP端口 try (DatagramSocket server = new DatagramSocket(PORT)) { server.setSoTimeout(10000); while (true) { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); try { server.receive(packet);//10s超时接收 byte[] now = new Date().toString().getBytes("US-ASCII"); //组织数据,并传入请求方socket地址作为回应地址 DatagramPacket outgoingPacket = new DatagramPacket(now, now.length, packet.getAddress(), packet.getPort()); server.send(outgoingPacket); } catch (SocketTimeoutException ex) { System.out.println("Timeout!");//超时 } catch (IOException ex) { ex.printStackTrace(); } } } catch (SocketException ex) { ex.printStackTrace(); } }}
UDP向底层IP数据添加少部分内容:源端口、目的端口、IP数据部分长度和可选校验和,这些总共占用8字节。端口、地址、数据长度和数据等信息都可以从DatagramPacket中提取或者向其设置,以上UDPServer.java就是提取这些信息而获取客户端信息并作为回应地址的。UDP包中数据理论最大为65507(65535-20IP基本头-8UDP头),但实际上几乎总是比这个少得多,在很多平台上往往限制在8KB,因此某些程序依赖于发送超过8KB数据的UDP包要多加小心,大多数情况下更大的包都会被简单地截取位8KB数据,为保证最大的安全性,UDP数据部分尽量保持在512B以下。下面是与UDPServer.java通信的示例客户端:
UDPClient.java
import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketTimeoutException;/** * Created by Cheney Hwang on 2017/5/9. */public class UDPClient { public final static int PORT = 5555; public final static String HOST = "localhost"; public static void main(String[] args) { try (DatagramSocket socket = new DatagramSocket()) {//绑定端口由系统分配 //DatagramSocket依赖于数据报DatagramPacket收发数据,byte[1]是为了触发服务端 DatagramPacket packet = new DatagramPacket(new byte[1], 1, InetAddress.getByName(HOST), PORT); socket.setSoTimeout(10000);//receive数据阻塞等待10s,超过这个时间仍未收到数据说明丢失了 socket.send(packet); DatagramPacket incomePacket = new DatagramPacket(new byte[64], 64); try { socket.receive(incomePacket);//阻塞接收,10s超时 byte[] nowByte = new byte[incomePacket.getLength()]; System.arraycopy(incomePacket.getData(), 0, nowByte, 0, incomePacket.getLength()); String now = new String(nowByte, "US-ASCII"); System.out.println(now); } catch (SocketTimeoutException ex) { System.out.println("Timeout!"); } } catch (IOException ex) { return; } }}
观察上面服务端和客户端的UDP通信示例,可以发现判断DatagramPacket是发数据还是收数据依据的是其构造差异。发数据在构造函数中需要指定目的Socket地址,而收数据并不需要(在生产环境中必须要考虑这边的安全策略)。类似地,DatagramSocket在默认构造时常用于客户端——其并不关心某个本地端口,由系统指定即可;而指定端口的构造常用于服务端,意义不言而喻。
这边还有个UDP应用场景需要注意的问题,UDP服务器一般不会与客户端做太多的交互,通常可以在连接线程中直接响应客户端。不过如果需要做大量处理的话,可以创建处理线程来做此工作。
- Java UDP通信:DatagramSocket和DatagramPacket
- Java.UDP.DatagramSocket-DatagramPacket
- Java.UDP.DatagramSocket-DatagramPacket
- Java学习之UDP--DatagramSocket和DatagramPacket
- Java----(UDP)DatagramPacket与DatagramSocket
- Java UDP通信(DatagramPacket类、DatagramSocket类、InetAddress类)
- Java UDP通信(DatagramPacket类、DatagramSocket类、InetAddress类)
- 网络 UDP通信 DatagramPacket DatagramSocket String
- java-----UDP---DatagramPacket类与DatagramSocket类
- java之UDP(datagramsocket,datagramPacket)实例
- 基于java的Udp探索,DatagramSocket ,DatagramPacket
- UDP DatagramPacket DatagramSocket
- java.net包的DatagramSocket和DatagramPacket
- java.net.DatagramPacket/java.net.DatagramSocket-UDP Socket编程
- java.net.DatagramPacket/java.net.DatagramSocket-UDP Socket编程
- [java] DatagramSocket DatagramPacket
- Java.UDP-TCP-DatagramSocket-DatagramPacket-InetAddress-ServerSocket-Socket
- 在Java中实现UDP协议编程(DatagramSocket/DatagramPacket)
- Observed package id 'build-tools;XX.X.X' in inconsistent location
- Numpy 数组操作
- 解决com.mysql.jdbc.PacketTooBigException: Packet for query is too large问题
- Multicast Sockets
- 算法笔记(IX) 一个随机数生成问题
- Java UDP通信:DatagramSocket和DatagramPacket
- web.xml配置详解之filter
- Jenkins进阶系列之——09配置Linux系统ssh免密码登陆
- Golang--string操作
- Vijos P1975 扫雷游戏【谜题】
- popwindow最有效解决弹窗屏幕背景阴影和取消阴影
- 2017.05.09回顾 pandas使用记录
- OpenGL ES入门05-OpenGL ES 纹理贴图
- 文章标题