Java UDP 数据包只有 5 位
Java UDP packet only holds 5 bites
以下代码用于发送以下格式的简单字符串 "address,porttNum"。
这是客户端:
ByteArrayInputStream bin = new ByteArrayInputStream(packet.getData());
DataInputStream dis = new DataInputStream(bin);
try {
System.out.println("Data in packet: " + dis.readLine());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
这是服务器端:
byte[] sbuf = data.getBytes();
// sbuf = output.getBytes();
packet = new DatagramPacket(sbuf,
sbuf.length, packet.getAddress(), packet.getPort());
try {
socket = new DatagramSocket();
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
假设服务器发送"abcdefghi",客户端只接收"abcde"。我已经尝试过多个测试用例,客户端总是收到 5 个字节。谁能指出我哪里搞砸了?
编辑:
出于调试目的,我什至添加了以下内容:
try {
System.out.println("Data in packet: " + dis.readLine());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
输出正确的数据,但客户端仍然没有得到它。
编辑 2:
我将客户端更改为以下内容:
String data = new String(packet.getData(), StandardCharsets.UTF_8);
System.out.println("Data in packet: " + data);
没有区别。
下面是一些示例代码,展示了从字符串的字节构造数据报包、发送它以及重建字符串。
请注意,创建的用于接收数据包的缓冲区比最终接收到的消息要大得多。这是必要的,因为 UDP 套接字如果接收到大于缓冲区的消息,会将消息截断为缓冲区的大小。例如,如果客户端将消息 "ZYXWV" 发送到服务器,并且只为该消息创建了足够大的缓冲区,然后 重新使用 传入消息的缓冲区,仅将收到传入消息的前 5 个字符。
public class DataGram {
public static void main(String[] args) throws SocketException {
new Thread(new Client()).start();
new Thread(new Server()).start();
}
static class Client implements Runnable {
DatagramSocket socket;
Client() throws SocketException {
socket = new DatagramSocket(1234);
}
@Override
public void run() {
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
try {
socket.receive(packet);
String msg = new String(packet.getData());
System.out.println(msg);
} finally {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class Server implements Runnable {
@Override
public void run() {
SocketAddress address = new InetSocketAddress("localhost", 1234);
try (DatagramSocket socket = new DatagramSocket()) {
String msg = "abcdefghi";
byte[] buf = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, address);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这里没有使用 DataInputStream 或 ByteArrayInputStream,因为您可以直接将 String
转换为 byte[]
然后再转换回来。
以下代码用于发送以下格式的简单字符串 "address,porttNum"。
这是客户端:
ByteArrayInputStream bin = new ByteArrayInputStream(packet.getData());
DataInputStream dis = new DataInputStream(bin);
try {
System.out.println("Data in packet: " + dis.readLine());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
这是服务器端:
byte[] sbuf = data.getBytes();
// sbuf = output.getBytes();
packet = new DatagramPacket(sbuf,
sbuf.length, packet.getAddress(), packet.getPort());
try {
socket = new DatagramSocket();
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
假设服务器发送"abcdefghi",客户端只接收"abcde"。我已经尝试过多个测试用例,客户端总是收到 5 个字节。谁能指出我哪里搞砸了?
编辑: 出于调试目的,我什至添加了以下内容:
try {
System.out.println("Data in packet: " + dis.readLine());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
输出正确的数据,但客户端仍然没有得到它。
编辑 2: 我将客户端更改为以下内容:
String data = new String(packet.getData(), StandardCharsets.UTF_8);
System.out.println("Data in packet: " + data);
没有区别。
下面是一些示例代码,展示了从字符串的字节构造数据报包、发送它以及重建字符串。
请注意,创建的用于接收数据包的缓冲区比最终接收到的消息要大得多。这是必要的,因为 UDP 套接字如果接收到大于缓冲区的消息,会将消息截断为缓冲区的大小。例如,如果客户端将消息 "ZYXWV" 发送到服务器,并且只为该消息创建了足够大的缓冲区,然后 重新使用 传入消息的缓冲区,仅将收到传入消息的前 5 个字符。
public class DataGram {
public static void main(String[] args) throws SocketException {
new Thread(new Client()).start();
new Thread(new Server()).start();
}
static class Client implements Runnable {
DatagramSocket socket;
Client() throws SocketException {
socket = new DatagramSocket(1234);
}
@Override
public void run() {
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
try {
socket.receive(packet);
String msg = new String(packet.getData());
System.out.println(msg);
} finally {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class Server implements Runnable {
@Override
public void run() {
SocketAddress address = new InetSocketAddress("localhost", 1234);
try (DatagramSocket socket = new DatagramSocket()) {
String msg = "abcdefghi";
byte[] buf = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, address);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这里没有使用 DataInputStream 或 ByteArrayInputStream,因为您可以直接将 String
转换为 byte[]
然后再转换回来。