C # UDP - можно ли указывать окнам отбрасывать пакеты через определенное время? - PullRequest
1 голос
/ 02 апреля 2012

У меня UDP-приложение с очень высокой скоростью, и мне немного любопытно узнать о конкретных основах здесь. Я использую асинхронные методы c # и на EndReceive, я помещаю работу в новый поток, затем вызываю BeginReceive.

Насколько я понимаю, даже если я в настоящее время нахожусь в коде между EndReceive и BeginReceive, Windows все еще принимает пакеты UDP на этом порту - и всякий раз, когда я снова вызываю BeginReceive, следующий будет забран из стека .

Предполагая, что все это верно (а если нет, пожалуйста, укажите прямо) - могу ли я указать TTL для этих пакетов? Мне нужно отправить ответ отправителю, и отправитель настроен на игнорирование ответов через несколько секунд.

Спасибо

Ответы [ 3 ]

4 голосов
/ 04 апреля 2012

Когда плата сетевого интерфейса доставляет дейтаграмму по проводам, операционная система помещает ее в очередь приема вашего сокета.Он ждет, пока вы не прочитаете его с помощью системного вызова recvfrom() или высокоуровневой оболочки по вашему выбору.

Размер этого буфера можно определить, вызвав getsockopt() для SO_RCVBUF.Размеры по умолчанию и максимальные размеры варьируются значительно в зависимости от операционной системы и версии.

Сетевые дейтаграммы не несут никакой информации о времени, поэтому не существует внутреннего способа их истечения в зависимости от времени.То, как вы решите действовать, зависит от того, откуда именно вы ожидаете задержек.

  • Если вас беспокоит время от отправки до обработки, то вы должны согласовать часы между отправителем иПолучатель, затем пусть отправитель поместит отметку времени в каждую датаграмму непосредственно перед отправкой.Это единственный способ узнать точное время между событиями.Но имейте в виду, что сетевая задержка может сильно различаться, поэтому простое отбрасывание всех пакетов старше некоторого количества может привести к отбрасыванию всех пакетов.

  • Если ваша проблема заключается втолько в течение промежутка времени между получением пакета и его обработкой (без учета задержек в сети) вам потребуется отдельный поток, считывающий дейтаграммы так быстро, как они поступают, записывает их время и сохраняет их во внутреннем,потокобезопасная очередь.Это большая работа, которая потребует значительных накладных расходов, поэтому вы, возможно, сначала захотите выяснить, почему происходит задержка в обработке.

  • Если пакеты отправляются с довольно фиксированной скоростьюи / или ваша проблема не столько с синхронизацией, сколько с наличием невыполненных невыполненных пакетов, тогда вы можете просто захотеть уменьшить размер очереди приема (setsockopt() с SO_RCVBUF).Пока очередь приема заполнена, все поступающие дейтаграммы будут молча отбрасываться.

1 голос
/ 04 мая 2012

Вы сможете указать TTL при отправке, но TTL уменьшается с каждым маршрутизатором по мере прохождения и не зависит от времени. Это не поле, которое вы ищете.

Таким образом, если пакет имеет TTL, равный трем, он становится равным 2 после первого маршрутизатора, 1 после второго маршрутизатора и 0 на третьем маршрутизаторе, где пакет будет отброшен без какого-либо уведомления отправителя.

1 голос
/ 02 апреля 2012

Ваше требование отбрасывать пакеты, когда они становятся слишком старыми, зависит от приложения и (AFAIK) не является чем-то, что UDP может предоставить вам. Windows может «автоматически» получать и буферизовать дейтаграммы для вас, но как это происходит, это деталь реализации сетевого стека.

Я бы разделил это на две части:

  1. Получать и ставить сообщения в очередь так же быстро, как они поступают.
    • Возможно, начните отбрасывать самые старые сообщения даже на этом этапе, если вы хотите ограничить размер своей очереди приема.
  2. Сообщения из очереди:
    • Бросить их на пол, если они слишком старые.
    • Обработка и подтверждение их в противном случае.

Шаг 2, вероятно, можно распараллелить, чтобы убедиться, что ваши потребители не отставали.

...