在学习udp数据通信的时候偶遇一个bug,具体代码如下
code
sender
package com.udpExample.chat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* TODO sender
*
* @author pangyangjian
* @since 2023/9/7 20:02
*/
public class UDPSender {
public static void main(String[] args) throws Exception {
DatagramSocket datagramSocket = new DatagramSocket(9090);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
// 控制台读取数据
String s = bufferedReader.readLine();
byte[] bytes = s.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(
"localhost", 9191));
datagramSocket.send(datagramPacket);
if ("end".equals(s)) {
break;
}
}
datagramSocket.close();
}
}
receiver
package com.udpExample.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* TODO receiver
*
* @author pangyangjian
* @since 2023/9/7 20:02
*/
public class UDPReceive {
public static void main(String[] args) throws Exception {
DatagramSocket datagramSocket = new DatagramSocket(9191);
while (true) {
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);
byte[] data = datagramPacket.getData();
String s = new String(data);
System.out.println(datagramPacket.getAddress() + " " + s.trim());
if ("end".equals(s)) {
break;
}
}
datagramSocket.close();
}
}
bug phenomenon
运行接收端的时候,控制台出bug,会一直输出null,不会等待接收sender发送的数据
解释
在receiver中,问题出现在以下行:
byte[] data = datagramPacket.getData();
String s = new String(data);
在这里先从datagramPacket
对象中获取了数据的引用,然后将其转换为字符串。然而,这是一个错误的方式。
在接收UDP数据报时,应该先调用receive()
方法来填充datagramPacket
对象数据,然后通过getData()
方法获取已接收的数据,而不是在还没有接收任何数据之前就尝试获取它。
以下是修复后的代码:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPReceive {
public static void main(String[] args) throws Exception {
DatagramSocket datagramSocket = new DatagramSocket(9191);
while (true) {
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
datagramSocket.receive(datagramPacket); // 接收数据
byte[] data = datagramPacket.getData();
String s = new String(data).trim();
System.out.println(datagramPacket.getAddress() + " " + s);
if ("end".equals(s)) {
break;
}
}
datagramSocket.close();
}
}
在修复后的代码中,我们通过调用datagramSocket.receive(datagramPacket)
来接收数据,该方法会在接收到数据之前一直阻塞。然后我们将接收到的数据转换为字符串,并使用trim()
方法去除首尾空格。