java System.currenttimemillis() 在两台计算机之间有一个偏移量

java System.currenttimemillis() has an offset between two computers

我正在编写一个 ping 应用程序,用于测量两台计算机(A 和 B)之间的数据包 recv/send 时间。它测量 A->B->A 时间、A->B 时间和 B->A 时间。现在,我 运行 在计算 B->A 的平均时间时遇到了一些问题,它显示负值。计算机 B 在接收数据包时比计算机 A 有 "faster"/ 更长的时间。我正在使用我的自定义 class:

获取时间值
public class TimingClass {
    public static long getTime() {
        return System.currentTimeMillis();
    }
}

客户端应用程序的输出如下所示:

Time of start: 1483531410095 // Time when the packet was sent from the client
Time on B: 1483531410538 // Time taken on the server and appended to the message
Packet arrival time: 1483531410104 // Time taken when the packet arrived back on the client
13:03:21: Total=272 Rate=30/s Lost=0 AvgRTT=35ms MaxRTT=63 A->B=449 B->A=-414

现在您可以看到,当消息从服务器返回时,客户端显示的时间值小于服务器所用的时间。

这是 client/server 代码,只有 recv/send 消息的部分:

// This is the sender thread on the client sending 30msgs/s
msgHandler.writeMessage(createMessage());
private String createMessage() {
    long time = TimingClass.getTime();
    String timeStr = Long.toString(time);
    String message = "payload"; 

    messageId++;
    return messageId + "%" + timeStr + "-" + message;
}
// This is the server part running on the main thread
while ((msg = msgHandler.readMessage()) != null) {
        catcherTime = TimingClass.getTime();
        System.out.println("Message arrived: " + msg);
        msgHandler.writeMessage(appendTime(msg, catcherTime));
}
// This is the receiving thread on the client side
while ((line = messageIO.readMessage()) != null) {
    currentTime = TimingClass.getTime();
    diff = currentTime - initTime;
    messageAcc++;
    numberOfMsgs++;
    bufferElement.addListElement(currentTime, line);
    if (diff > 1000) {
        initTime = TimingClass.getTime();
        bufferElement.setMsgAcc(messageAcc);
        bufferElement.setMsgNumber(numberOfMsgs);
        queue.put((bufferElement));
        numberOfMsgs = 0;
        bufferElement = new BufferQueueElement();
    }
}

从代码中可以看出,打印出的值与上述时间变量的对应关系如下:

time -> Time of start
catcherTime -> Time on B
currentTime -> Packet arrival time

客户端每1秒处理一次消息。 那么,有没有人遇到过此类问题或知道如何变通或解决它?

P.S。 我试过使用 System.nanoTime() 但 A->B 平均时间开始显示负值。此外,一台机器是 运行 Windows 10(客户端),另一台是 Windows 8.1(服务器),它们通过家庭网络连接。我正在开发的最低 Java 版本是 5,两台机器都有 java 8。而且两台机器都通过 time.windows.com 同步,我在 运行 之前手动完成应用程序以确保它们已同步。

这是计算机科学中的一个已知问题,请参阅 Lamport timestamps。来自维基 link:

In a distributed system, it is not possible in practice to synchronize time across entities (typically thought of as processes) within the system; hence, the entities can use the concept of a logical clock based on the events through which they communicate.

想象一下有人在 phone 上,假设你们正在互相询问不需要思考的简单问题。每当您向另一端的人询问某事时,答复都会延迟几秒钟。现在您有两种情况:要么您的问题收到延迟,要么答案延迟送达。无法判断哪种情况是真实的。事实上,它通常都在不同的部分。

鉴于您只有两个 senders/receivers,无法判断延迟的来源。您需要第三个实例作为中央控制站。

您对两个节点唯一能做的就是测量包裹双向传送所需的时间。