gpt4 book ai didi

java - 为什么 Java 看不到 tcpdump 显示的传入 UDP 数据包已收到?

转载 作者:搜寻专家 更新时间:2023-11-01 03:55:27 24 4
gpt4 key购买 nike

我看到一个问题(SLES11 上的 Java 6),其中一个 UDP 数据包被发送回客户端机器(并且客户端机器上的 tcpdump 显示它被接收),但是数据包没有' 被 Java 看到。

测试是这样的:

客户端生成一些随机数据,将其放入 UDP 数据包中,通过特定端口将其发送到服务器并等待其回显(SO_TIMEOUT 为 180000 毫秒) .当它收到它时,它会打印出它已经收到它以及它被发送了多长时间。

服务器端在该端口上监听 UDP 数据包。当它收到它时,它会延迟一点然后立即将其发送回去,不变。延迟从某个初始值(3000 毫秒)开始,然后每次收到数据包时加倍,直到达到最大值(90000 毫秒),之后延迟保持在最大值。

在延迟达到 48000 毫秒之前它工作正常。客户端上运行的 tcpdump 显示正在发送的数据包,并显示 48000 毫秒后到达的回复数据包。但是,Java 程序永远不会看到该回复数据包,并且在 180000 毫秒后声称接收超时。尽管客户端计算机仅在 48000 毫秒后收到数据包,如 tcpdump 所示。

会发生什么?

下面是程序和tcpdump的输出,之后是客户端和服务器程序的源代码。

客户端机器上,测试程序输出为:

rich-ova3:~/UDPTest2 # java -cp . Client
Properties:
-- listing properties --
ServerPort=20000
Timeout=180000
Server=rich-ova5.teak.eng
Loops=8
DatagramLength=333

UDP socket timeout is 180000 ms
Sending packet 1 of 8
Received packet 1 of 8
Round-trip time: 3001 ms

Sending packet 2 of 8
Received packet 2 of 8
Round-trip time: 6001 ms

Sending packet 3 of 8
Received packet 3 of 8
Round-trip time: 12001 ms

Sending packet 4 of 8
Received packet 4 of 8
Round-trip time: 24000 ms

Sending packet 5 of 8
Error receiving: Receive timed out
java.net.SocketTimeoutException: Receive timed out
at java.net.PlainDatagramSocketImpl.receive0(Native Method)
at java.net.PlainDatagramSocketImpl.receive(Unknown Source)
at java.net.DatagramSocket.receive(Unknown Source)
at Client.go(Client.java:80)
at Client.main(Client.java:39)
Round-trip time: 180096 ms

Sending packet 6 of 8
Error receiving: Receive timed out
java.net.SocketTimeoutException: Receive timed out
at java.net.PlainDatagramSocketImpl.receive0(Native Method)
at java.net.PlainDatagramSocketImpl.receive(Unknown Source)
at java.net.DatagramSocket.receive(Unknown Source)
at Client.go(Client.java:80)
at Client.main(Client.java:39)
Round-trip time: 180087 ms

Sending packet 7 of 8
Error receiving: Receive timed out
java.net.SocketTimeoutException: Receive timed out
at java.net.PlainDatagramSocketImpl.receive0(Native Method)
at java.net.PlainDatagramSocketImpl.receive(Unknown Source)
at java.net.DatagramSocket.receive(Unknown Source)
at Client.go(Client.java:80)
at Client.main(Client.java:39)
Round-trip time: 180093 ms

Sending packet 8 of 8
Error receiving: Receive timed out
java.net.SocketTimeoutException: Receive timed out
at java.net.PlainDatagramSocketImpl.receive0(Native Method)
at java.net.PlainDatagramSocketImpl.receive(Unknown Source)
at java.net.DatagramSocket.receive(Unknown Source)
at Client.go(Client.java:80)
at Client.main(Client.java:39)
Round-trip time: 180078 ms

Send successes: 8
Send errors: 0

Receive successes: 4
Receive errors: 4

客户端 机器上的tcpdump 输出(我的评论内嵌)是:

16:03:42.438252 IP 172.16.20.113.16362 > 172.16.20.115.20000: UDP, length 333
16:03:45.439322 IP 172.16.20.115.20000 > 172.16.20.113.16362: UDP, length 333
(a 3011 ms delay)

16:03:45.440315 IP 172.16.20.113.25559 > 172.16.20.115.20000: UDP, length 333
16:03:51.441394 IP 172.16.20.115.20000 > 172.16.20.113.25559: UDP, length 333
(a 6001 ms delay)

16:03:51.441938 IP 172.16.20.113.30457 > 172.16.20.115.20000: UDP, length 333
16:04:03.442564 IP 172.16.20.115.20000 > 172.16.20.113.30457: UDP, length 333
(a 12000 ms delay)

16:04:03.443095 IP 172.16.20.113.46143 > 172.16.20.115.20000: UDP, length 333
16:04:27.443572 IP 172.16.20.115.20000 > 172.16.20.113.46143: UDP, length 333
(a 24001ms delay)

16:04:27.444109 IP 172.16.20.113.31747 > 172.16.20.115.20000: UDP, length 333
16:05:15.444688 IP 172.16.20.115.20000 > 172.16.20.113.31747: UDP, length 333
(a 48001 ms delay)

16:07:27.540689 IP 172.16.20.113.38357 > 172.16.20.115.20000: UDP, length 333
16:08:57.541312 IP 172.16.20.115.20000 > 172.16.20.113.38357: UDP, length 333
(a 90000 ms delay)

16:10:27.627411 IP 172.16.20.113.33915 > 172.16.20.115.20000: UDP, length 333
16:11:57.631436 IP 172.16.20.115.20000 > 172.16.20.113.33915: UDP, length 333
(a 90004 ms delay)

16:13:27.720668 IP 172.16.20.113.36494 > 172.16.20.115.20000: UDP, length 333
16:14:57.722353 IP 172.16.20.115.20000 > 172.16.20.113.36494: UDP, length 333
(a 90001 ms delay)

服务器机器上,测试程序输出为:

rich-ova5:~/UDPTest2 # java -cp . Server
Properties:
-- listing properties --
MinSleepTime=1000
DatagramLength=333
MaxSleepTime=90000
Port=20000

Received packet.
Delaying for 3000 ms
Sending packet.

Received packet.
Delaying for 6000 ms
Sending packet.

Received packet.
Delaying for 12000 ms
Sending packet.

Received packet.
Delaying for 24000 ms
Sending packet.

Received packet.
Delaying for 48000 ms
Sending packet.

Received packet.
Delaying for 90000 ms
Sending packet.

Received packet.
Delaying for 90000 ms
Sending packet.

Received packet.
Delaying for 90000 ms
Sending packet.

这是客户端来源:

import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;
import java.util.Random;

public class Client {
private static final String CONFIG_FILE = "client.conf";

private int datagramLength;
private boolean debug;
private InetAddress server;
private int serverPort;
private int timeout;
private int loops;

public static void main(String[] arg) throws Exception {
Client c = new Client();
c.go();
}

private void go() throws Exception {
readClientConfig();
Random rand = new Random(System.currentTimeMillis());

System.out.println("UDP socket timeout is " + timeout + " ms");

byte[] referenceData = new byte[datagramLength];
byte[] sentData = new byte[referenceData.length];

int receiveErrors = 0;
int receiveSuccess = 0;
int sendErrors = 0;
int sendSuccess = 0;

for (int i = 0; i < loops; i++) {
long sendTime = 0;
long receiveTime = 0;

rand.nextBytes(referenceData);
System.arraycopy(referenceData, 0, sentData, 0, referenceData.length);

DatagramSocket serverSock = new DatagramSocket();
serverSock.setSoTimeout(timeout);

DatagramPacket datagram = new DatagramPacket(sentData, sentData.length, server, serverPort);
try {
System.out.println("Sending packet " + (i + 1) + " of " + loops);
serverSock.send(datagram);
sendSuccess++;
} catch (Exception e) {
System.out.println("Error sending: " + e.getMessage());
e.printStackTrace();
sendErrors++;
continue;
}
sendTime = System.currentTimeMillis();

try {
serverSock.receive(datagram);
System.out.println("Received packet " + (i + 1) + " of " + loops);
receiveSuccess++;
} catch (Exception e) {
receiveErrors++;
System.out.println("Error receiving: " + e.getMessage());
e.printStackTrace();
}
serverSock.close();

receiveTime = System.currentTimeMillis();
System.out.println("Round-trip time: " + (receiveTime - sendTime) + " ms");

byte[] receivedData = datagram.getData();
if (receivedData.length != referenceData.length) {
System.out.println("Mismatched packet length.");
sendErrors++;
}

for (int j = 0; j < datagramLength; j++) {
if (referenceData[j] != receivedData[j]) {
System.out.println("Mismatched packet contents.");
sendErrors++;
}
}

System.out.println();
}

System.out.println("Send successes: " + sendSuccess);
System.out.println("Send errors: " + sendErrors);
System.out.println();
System.out.println("Receive successes: " + receiveSuccess);
System.out.println("Receive errors: " + receiveErrors);
}

private void readClientConfig() throws IOException {
boolean hasError = false;
String val;
Properties prop = new Properties();

FileInputStream fis = new FileInputStream(CONFIG_FILE);
prop.load(fis);

val = prop.getProperty("Server");
if (val == null) {
System.out.println("Error reading 'Server': missing value");
hasError = true;
} else {
try {
server = InetAddress.getByName(val);
} catch (UnknownHostException e) {
System.out.println("Error reading 'Server': " + e.getMessage());
hasError = true;
}
}

val = prop.getProperty("ServerPort", "3000");
try {
serverPort = Integer.parseInt(val);
} catch (NumberFormatException e) {
System.out.println("Error reading 'ServerPort': " + e.getMessage());
hasError = true;
}

val = prop.getProperty("DatagramLength", "200");
try {
datagramLength = Integer.parseInt(val);
} catch (NumberFormatException e) {
System.out.println("Error reading 'DatagramLength': " + e.getMessage());
hasError = true;
}

// Time out in milliseconds.
val = prop.getProperty("Timeout", "3000");
try {
timeout = Integer.parseInt(val);
} catch (NumberFormatException e) {
System.out.println("Error reading 'Timeout' value.");
hasError = true;
}

// Number of loops to perform.
val = prop.getProperty("Loops", "1");
try {
loops = Integer.parseInt(val);
} catch (NumberFormatException nfe) {
System.out.println("Error reading 'Loops' value.");
hasError = true;
}
val = prop.getProperty("EnableDebug", "yes");
debug = val.equalsIgnoreCase("yes");

System.out.println("Properties:");
prop.list(System.out);
System.out.println();

if (hasError) {
System.out.println("There are errors - fix them and restart the server.");
System.exit(1);
}
}

}

服务器来源:

import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Properties;

public class Server {
private static final String CONFIG_FILE = "server.conf";

private int datagramLength;
private boolean debug;
private int port;
private long initialDelay;
private long maxDelay;

public static void main(String[] arg) throws Exception {
Server s = new Server();
s.go();
}

private void go() throws Exception {
readServerConfig();

DatagramSocket sock = new DatagramSocket(port);

sock.setSoTimeout(0);

byte[] in = new byte[datagramLength];
DatagramPacket datagram = new DatagramPacket(in, datagramLength);

// Loop with exponentially-increasing delays between receive
// and reply (up to the specified maximum delay).
long delay = initialDelay;
while (true) {
sock.receive(datagram);
System.out.println("Received packet.");

System.out.println("Delaying for " + delay + " ms");
Thread.sleep(delay);

System.out.println("Sending packet.");

datagram.setSocketAddress(datagram.getSocketAddress());
datagram.setPort(datagram.getPort());
sock.send(datagram);

System.out.println();

delay *= 2;
if (delay > maxDelay) {
delay = maxDelay;
}
}
}

private void readServerConfig() throws IOException {
boolean hasError = false;
String val;
Properties prop = new Properties();

FileInputStream fis = new FileInputStream(CONFIG_FILE);
prop.load(fis);

val = prop.getProperty("Port", "3000");
try {
port = Integer.parseInt(val);
} catch (NumberFormatException e) {
System.out.println("Error reading 'Port' value: " + e.getMessage());
hasError = true;
}

val = prop.getProperty("DatagramLength", "200");
try {
datagramLength = Integer.parseInt(val);
} catch (NumberFormatException e) {
System.out.println("Error reading 'DatagramLength' value: " + e.getMessage());
hasError = true;
}

val = prop.getProperty("StartSleepTime", "3000");
try {
initialDelay = Long.parseLong(val);
} catch (NumberFormatException e) {
System.out.println("Error reading 'StartSleepTime' value: " + e.getMessage());
hasError = true;
}

val = prop.getProperty("MaxSleepTime", "60000");
try {
maxDelay = Long.parseLong(val);
} catch (NumberFormatException e) {
System.out.println("Error reading 'MaxSleepTime' value: " + e.getMessage());
hasError = true;
}

val = prop.getProperty("EnableDebug", "yes");
debug = val.equalsIgnoreCase("yes");

System.out.println("Properties:");
prop.list(System.out);
System.out.println();

if (hasError) {
System.out.println("There are errors - fix them and restart the server.");
System.exit(1);
}
}

}

client.conf:

# Server address
Server = rich-ova5.teak.eng

# Server port number.
ServerPort = 20000

# This is the length of the data to send.
# It must match the server's size.
DatagramLength = 333

# Number of times to run the client.
Loops = 8

# Client time out period in milliseconds.
Timeout = 180000

最后,server.conf:

# Server port number.
Port=20000

# Length of the datagram.
# It must match the client's size.
DatagramLength = 333

# Initial sleep time.
MinSleepTime = 1000

# Maximu sleep time. Goes from the MinSleepTime to the
# maximum sleep time.
MaxSleepTime = 90000

最佳答案

如果可能,也许检查 tcpdump 捕获中数据包的 IPv4 TTL(生存时间)。

48 秒后,由于 TTL,数据包可能会被接收方的 IP 堆栈接收但被丢弃。

另请参阅有关更改 TTL 的答案(它表示它仅适用于多播套接字,但无论如何都被接受):Java control IP TTL?

关于java - 为什么 Java 看不到 tcpdump 显示的传入 UDP 数据包已收到?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8527111/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com