Java实现UDP通信过程

UDP 是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象。因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念。Java提供了DatagramSocket类作为基于UDP协议的Socket。
接收端一直在检测,有消息接受就行。

接收数据的步骤
① 创建接收端的 Socket 对象 ( DatagramSocket )
② 创建一个数据包,用于接收数据
③ 调用 DatagramSocket 对象的方法接收数据
④ 解析数据包,并把数据在控制台 显示
⑤ 关闭接收端

TCP是一种面向连接的传输层协议,而UDP是传输层中面向无连接的协议,故传送的数据包不能保证有序和不丢失,实现UDP通信主要用到了两个类:DatagramPacketDatagramSocket

DatagramSocket
这个类用来表示发送和接收数据包的套接字。

//构造方法,创建数据报套接字并将其绑定到本地主机上的指定端口
//创建数据包传输对象DatagramSocket 绑定端口号
DatagramSocket dsGz = new DatagramSocket(udpPort);

DatagramPacket

表示数据报包,用来实现无连接的包的投递服务。这些数据包选择不同的路由,经过计算机的存储转发,最终到达目的计算机。所以到达的数据包和发送时的顺序不一定会相同。

java udt协议 java实现udp协议_网络协议

图来自网络

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();
        }
    }
}