什么是UDP协议以及它的使用优点:百度的解释是这样的:Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。
- 不需要要建立连接
- 开销小
- 速度快
一:udp通信主要使用的场景:
比如设备监控,监控设备是否脱机,目前我主要是用于在同一个局域网内模拟设备给手机app发送数据,app界面需要显示该设备的一个工作情况,比如车辆的转速 工作时间 当前电量 待机 预热情况等,那么中间就有一个接收模拟设备发送过来的报文数据,以及当我接收完数据的一个显示情况,作为app端只需要接收数据,所以下面的内容主要是介绍app端接收udp的报文数据。
二:udp通信 接收数据方的流程:
- 创建Socket对象 ( DatagramSocket)
- 创建一个接收数据的包 (DatagramPacket)下面代码创建了一个接收线程 每沉睡20毫秒后receive数据
- 解析数据包 大致代码如下
private DatagramSocket receiveSocket = null;// 接收数据Socket private DatagramPacket rPacket = null; private DatagramPacket packet = null; private Thread rthread = null;// 接收数据线程
/*** 接收数据socket连接 ***/
private void connectSocket() {
DisConnectSocket();
try {
if (receiveSocket == null) {
receiveSocket = new DatagramSocket(null);
receiveSocket.setReuseAddress(true);
receiveSocket.bind(new InetSocketAddress(port));
}
if (rPacket == null) {
rPacket = new DatagramPacket(rBuffer, rBuffer.length);
}
if (rthread == null) {
//创建接收线程
ReceiveDataThread receiveDataThread = new ReceiveDataThread();
rthread = new Thread(receiveDataThread);
rthread.start();
}
} catch (Exception e) {
e.printStackTrace();
ToastUtils.showShort("连接本地端口:" + localPort + "失败,异常代码:" + e.getMessage(),Toast.LENGTH_LONG);
DisConnectSocket();
}
}
class ReceiveDataThread implements Runnable {
@Override
public void run() {
Boolean aBoolean = false;
if(Thread.currentThread() == rthread){
while (Thread.currentThread() == rthread) {
//接收报文数据
recvData();
Thread.sleep(20);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
/****
* 接收数据
*
* @return
*/
private boolean recvData() {
try {
if (receiveSocket != null) {
try {
//设置超时时间
receiveSocket.setSoTimeout(2000);
receiveSocket.receive(rPacket);
// sRecvData 是接收到的报文数据
if (isRHex) {
sRecvData = recvHexData(rPacket.getLength());
} else {
sRecvData = new String(rPacket.getData(), currentRCodes)
.trim();
}
aBoolean = false;
} catch (Exception e) {
sRecvData = null;
aBoolean = true;
}
} else {
ToastUtils.showShort("没有连接本地端口!",Toast.LENGTH_LONG);
return false;
}
return aBoolean;
} catch (Exception e) {
// ToastUtils.showShort("接收数据错误,异常代码:"+ e.getMessage(),Toast.LENGTH_LONG);
return aBoolean;
}
}
三:我遇到的问题
当模拟设备不给app端发数据时需要清空界面数据,can转WiFi模块(模拟设备)设置的是20毫秒会发送一次数据,但udp通信是没有接收到数据会处于阻塞状态,receive();方法会一直等待数据接收,直到有数据接收到的时候就会结束阻塞,解决方法: receiveSocket.setSoTimeout(2000); 设置2s超时等待,如果2s还是没有接收到数据就抛出异常,那么就可以在catch里面去调用界面参数的清空方法。

本文深入解析了UDP协议的特点与优势,并详细介绍了在APP端如何通过创建Socket对象接收UDP数据的具体流程,包括接收线程的实现与异常处理,特别关注了在未接收到数据时的界面更新策略。
537

被折叠的 条评论
为什么被折叠?



