2017-01-04 16 views
1

Я пишу приложение ping, которое измеряет время возврата/отправки пакетов между двумя компьютерами (A и B). Он измеряет A-> B-> A время, A-> B время и B-> A время. Теперь я столкнулся с некоторыми проблемами при вычислении среднего времени для B-> A, он показывает отрицательные значения. Компьютер B имеет «более быстрое»/большее время, чем компьютер A при приеме пакета. Я принимаю значение времени, используя свой собственный класс:java System.currenttimemillis() имеет смещение между двумя компьютерами

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 

Клиент обрабатывает сообщения через каждые 1 с. Итак, есть ли у кого-нибудь какие-либо эксперименты с подобной проблемой или они знают, как обходить ее или решать?

P.S. Я пробовал использовать System.nanoTime(), но тогда среднее время A-> B показывает отрицательные значения. Кроме того, на одной машине работает Windows 10 (клиент), другой Windows 8.1 (сервер), и они подключены через домашнюю сеть. Минимальная версия Java, которую я разрабатываю, равна 5, обе машины имеют java 8. Также обе машины синхронизируются с time.windows.com, я сделал это вручную перед запуском приложения, чтобы убедиться, что они синхронизированы.

+2

Может ли это быть связано с ведущим вторым, которое мы «получаем» на прошлой неделе? У вас есть точно такая же версия java на обеих машинах? –

ответ

2

Это известная проблема в информатике, см. Lamport timestamps. Из ссылки вики:

В распределенной системе, на практике невозможно синхронизировать времени через лицо (как правило, думают как процессы) в рамках системы ; следовательно, сущности могут использовать концепцию логических часов на основе событий, через которые они обмениваются данными.

+0

Хорошо, прочитав это, единственное решение, которое я вижу для точного измерения A-> B, B-> A, - это использование NTP-сервера для синхронизации обоих компьютеров?Поскольку, грубо говоря, алгоритм Lamports основан на пользовательских часах, которые могут быть уродливым решением, если нет хороших примеров/java-библиотек, которые уже имеют реализацию? –

+1

Я думаю, что общий смысл работы Лампорта заключается в том, что вы не можете точно сравнить A-> B и B-> A. Единственное, что вы можете точно измерить, это поездка туда и обратно: A-> B-> A ... –

2

Представьте, что у вас есть кто-то по телефону и предположим, что вы задаете друг другу простые вопросы, которые не требуют мышления. Всякий раз, когда вы спрашиваете человека на другом конце чего-то, ответ приходит на несколько секунд. Теперь у вас есть два сценария: либо ваш вопрос был получен с задержкой, либо ответ был отложен. Невозможно определить, какой сценарий является истинным. Фактически, это обычно как в разных частях.

Учитывая, что у вас есть только два отправителя/приемника, нет способа сообщить, откуда идет задержка. Вам понадобится третий экземпляр, который действует как центральная станция управления.

Единственное, что вы можете сделать с двумя узлами - это измерение времени, которое требуется для того, чтобы пакет проходил в обоих направлениях.

 Смежные вопросы

  • Нет связанных вопросов^_^