2017-01-04 4 views
1

私は2台のコンピュータ(AとB)間のパケット受信/送信時間を測定するpingアプリケーションを作成しています。 A→B→A時間、A→B時間、B→A時間を測定します。さて、私はB - > Aの平均時間を計算するときにいくつかの問題に遭遇しました、それは負の値を示しています。コンピュータBは、パケットを受信するときにコンピュータAよりも「より速い」/より長い時間を有する。java System.currenttimemillis()は2台のコンピュータ間にオフセットを持っています

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 

今あなたがた場合に、クライアントが小さい時間値を示していることがわかります私は私のカスタムクラスを使用して時刻の値を取っていますメッセージがサーバーから取られた時間よりもサーバーから戻されました。コードから

// 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 
ここ

は、クライアント/サーバ・コード、RECV /送信メッセージが部分のみです

クライアントは、1秒ごとにメッセージを処理します。 だから、誰かがこの種の問題に関して何らかの経験を持っているのですか、それを回避するか解決する方法を知っていますか?

P.S. 私はSystem.nanoTime()を使ってみましたが、A - > B平均時間が負の値を示し始めました。また、一方のマシンではWindows 10(クライアント)を実行し、もう一方のマシンではWindows(サーバー)を実行し、ホームネットワーク経由で接続します。私が開発している最小Javaバージョンは5で、両方のマシンにjava 8があります。また、両方のマシンがtime.windows.comで同期されています。同期させるためにアプリを実行する前に手動で行っています。

+2

先週、私たちが先に "獲得"するリードにリンクできますか?あなたは両方のマシンにまったく同じバージョンのjavaを持っていますか? –

答えて

2

これはコンピュータサイエンスの既知の問題です。Lamport timestampsを参照してください。ウィキリンクから:分散システムにおいて

、 システム内のエンティティ(通常プロセスと考える)を横切る 時間を同期させるために実際には不可能です。エンティティは、それらが通信するイベントに基づいて論理時計 の概念を使用することができる。

+0

これを読んで、A-> B、B-> Aを正確に測定するための唯一の解決策は、両方のコンピュータを同期させるためにNTPサーバーを使用することによるものですか?大まかにLamportsのアルゴリズムはカスタムメイドのクロックに基づいているので、すでに実装されている良い例やJavaライブラリがない限り、醜い解決策になる可能性がありますか? –

+1

私はLamportの仕事の一般的な要点は、A→BとB→Aを正確に比較することができないということです。正確に測定できる唯一のものは、往復です:A-> B-> A ... –

2

誰かが電話をかけていると想像してみましょう。想像の必要のない簡単な質問をしているとしましょう。その相手に何かを尋ねると、その応答は数秒遅れる。今、あなたは2つのシナリオを持っています:あなたの質問が遅れて受け取られたか、答えが遅れて届けられました。どちらのシナリオが正しいかは分かりません。実際、それは通常、変化する部分の両方にあります。

送信者/受信者が2人しかないため、遅延がどこから来ているかを知る方法がありません。中央制御ステーションとして機能する第3のインスタンスが必要です。

2つのノードで行うことができるのは、パッケージが両方向に移動するのにかかる時間を測定することだけです。

関連する問題