Как определить, что пакет UDP был потерян? (С#)

Я разрабатываю клиент SNTP, который получает отметку времени с сервера NTP через UDP. Все работает нормально, я могу загрузить отметку времени и обновить часы Windows, но я хотел бы получить сообщение, если пакет UDP был потерян. Как я могу определить, когда пакет был потерян? Мне нужна эта информация, потому что я хочу получить новую отметку времени, если данные потеряны.

... и как я могу проверить эту функцию? Как я могу намеренно потерять UDP-пакет?


person user1528100    schedule 28.08.2012    source источник
comment
UDP является односторонним, вы не можете обнаружить, что пакет был потерян. Это основное различие между TCP и UDP.   -  person Kevin Gosse    schedule 28.08.2012
comment
Как именно работает этот сервис? Ваш клиент делает запрос на сервер и ждет ответа, после чего обновляет свое время? Или ваш клиент ждет и прослушивает пакеты UDP с сервера? В любом случае вы не можете проверить передачу UDP-пакетов. В зависимости от ваших потребностей установка тайм-аута может быть лучшим вариантом для вас? Показать предупреждение или создать исключение или что-то еще, если время не было обновлено в течение последних X секунд или что-то в этом роде?   -  person Kjartan    schedule 28.08.2012


Ответы (5)


У вас есть три варианта:

  1. Игнорировать потерянные пакеты
  2. Вместо этого используйте TCP
  3. Создайте свою собственную систему обнаружения

Вы спрашиваете, как сделать № 3, и ответ:

  • Добавьте номер пакета и метку времени пакета к каждому пакету.
  • Создайте стек пакетов и вставьте в стек входящие пакеты, отсортированные по номеру пакета.
  • Удалять пакеты из стека только тогда, когда есть пакет с номером пакета (номер последнего пакета + 1).
  • Если в пакетах есть разрыв и временная метка пакета (gap + 1) больше некоторого порога, отправьте пакет «запрос на повторную передачу», чтобы повторно передать отброшенный пакет.

Подожди секунду... именно так это делает TCP(*)! Вы должны просто использовать TCP!

(*) Это было упрощением, TCP проделывает большую работу, чтобы сделать процесс надежным.

person Tergiver    schedule 28.08.2012

Это невозможно с UDP. Если вам нужно надежное соединение, вы должны использовать TCP.

person ThiefMaster    schedule 28.08.2012
comment
+1, несмотря на то, что вы все еще можете реализовывать соединения с порядковыми номерами, подтверждениями и повторными передачами по UDP. Хотя это бессмысленно, мне пришлось сделать это как лабораторное задание (много часов и тестов, чтобы сделать это почти так же хорошо, как TCP, настоящая головная боль). - person NotGaeL; 28.08.2012

UDP — это протокол без установления соединения. Когда связи нет, у вас нет возможности что-либо «обнаружить». Вы должны использовать протокол, ориентированный на соединение, такой как TCP, чтобы решить эту проблему.

Сравнение

person Chathuranga Chandrasekara    schedule 28.08.2012

в порядке. Я понял. Но могу ли я проверить потерю пакетов, выполнив что-то подобное? Например, если я устанавливаю таймер на 2 секунды, а затем запускаю эту функцию, я вижу, правильно ли ответил сервер. Тогда я должен знать, была ли потеря пакетов?

public bool IsResponseValid()
    {
        if(SNTPData.Length < SNTPDataLength || Mode != _Mode.Server)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
person user1528100    schedule 28.08.2012
comment
Не устоял перед желанием оптимизировать код: return SNTPData.Length ›= SNTPDataLength && Mode == _Mode.Server; - person rmp251; 21.05.2014

Поскольку нет способа проверить, не удалось ли получить UDP, единственным верным вариантом будет префикс всех отправленных данных с «номером пакета», и поэтому, если это не следующий номер в строке, вы знаете, что он потерял пакет.

Насколько я знаю, нет никакого способа преднамеренно потерять 1 udp пакет, кроме как выдернуть кабель и заменить его.. и надеяться..

person BugFinder    schedule 28.08.2012