Java实现UDP通信过程
UDP 是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象。因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念。Java提供了DatagramSocket类作为基于UDP协议的Socket。
接收端一直在检测,有消息接受就行。
接收数据的步骤
① 创建接收端的 Socket 对象 ( DatagramSocket )
② 创建一个数据包,用于接收数据
③ 调用 DatagramSocket 对象的方法接收数据
④ 解析数据包,并把数据在控制台 显示
⑤ 关闭接收端
TCP是一种面向连接的传输层协议,而UDP是传输层中面向无连接的协议,故传送的数据包不能保证有序和不丢失,实现UDP通信主要用到了两个类:DatagramPacket和DatagramSocket。
DatagramSocket
这个类用来表示发送和接收数据包的套接字。
//构造方法,创建数据报套接字并将其绑定到本地主机上的指定端口
//创建数据包传输对象DatagramSocket 绑定端口号
DatagramSocket dsGz = new DatagramSocket(udpPort);
DatagramPacket
表示数据报包,用来实现无连接的包的投递服务。这些数据包选择不同的路由,经过计算机的存储转发,最终到达目的计算机。所以到达的数据包和发送时的顺序不一定会相同。
图来自网络
conf.properties
#是否开启UDP监听
udpSwitch = true
#UDP端口
udpPort = 30005
MicroVariation.java
@Data
@ApiModel(value = "MicroVariation", description = "UDP数据")
public class MicroVariation {
@ApiModelProperty(value = "参数ID")
private String id;
@ApiModelProperty(value = "当前值")
private String curValue;
@ApiModelProperty(value = "数据值描述")
private String valueDescript;
}
UdpServer.java
调用DatagramSocket(int port)创建一个数据报套接字,绑定在指定端口上;
调用DatagramPacket(byte[] buf,int length),建立一个字节数组来接收UDP包;
import com.alibaba.fastjson.JSONObject;
import com.cn.utils.StaticConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.List;
import java.util.ResourceBundle;
import static com.alibaba.fastjson.JSON.parseArray;
import static com.alibaba.fastjson.JSON.parseObject;
/**
* '@Description:' udp服务端接收.
* '@Author:'buzhidao
*/
@Slf4j
@Component
public class UdpServer implements ApplicationRunner {
private Boolean udpSwitch;
/**
* 获取UDP数据进行相应操作
*/
private void getUdpData(DatagramSocket ds) {
try {
while (udpSwitch) {
byte[] data = new byte[65535];
//创建数据包对象,传递字节数组
DatagramPacket dp = new DatagramPacket(data, 0, data.length);
//调用ds对象的方法receive传递数据包
ds.receive(dp);
//存储数据的String
String updData = new String(dp.getData(), 0, dp.getLength());
//接收到UDP数据的结尾
/**
下面部分可根据自己的数据格式、类型自行修改
*/
if (updData.endsWith("]}")) {
JSONObject microVariationVO = parseObject(updData);
if (microVariationVO.getString("DevProp") != null) {
List<MicroVariation> microVariationList = parseArray(microVariationVO.getString("DevProp"), MicroVariation.class);
//数据存储
for (MicroVariation microVariation : microVariationList) {
if (StaticConstant.UDP_COLLECTION_ACTIVE_POWER_PARAMETER_NO.contains(microVariation.getID())) {
//TODO 数据操作...
}
}
}
}
}
} catch (Exception e) {
log.info("UDP异常:" + e.getMessage());
e.printStackTrace();
if (ds != null) {
ds.close();
}
this.udpConnect();
}
}
@Override
public void run(ApplicationArguments args) {
//UDP连接
this.udpConnect();
}
public void udpConnect() {
try {
//是否开启UDP服务
udpSwitch = Boolean.parseBoolean(ResourceBundle.getBundle("conf").getString("udpSwitch"));
//UDP端口
int udpPort = Integer.parseInt(ResourceBundle.getBundle("conf").getString("udpPort"));
if (udpSwitch) {
log.info("UDP服务端启动:" + udpPort);
//创建数据包传输对象DatagramSocket 绑定端口号
DatagramSocket dsGz = new DatagramSocket(udpPort);
//微动数据存储
this.getUdpData(dsGz);
}
} catch (Exception e) {
log.info("UDP服务端异常");
e.printStackTrace();
}
}
}