(随笔)udp接收数据 bugfix

发布时间 2023-09-08 10:59:28作者: Joseph·Jonardo

在学习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()方法去除首尾空格。