UDP: сомнения относительно записи () и времени ожидания сокета (SO_SNDTIMEO), когда буфер сокета заполнен - PullRequest
0 голосов
/ 02 ноября 2018

У меня возникают проблемы с пониманием того, как буферы сокетов и тайм-ауты управляются в Linux при использовании UDP. Я использую дистрибутив OpenWrt для Linux с ядром версии 4.14.63.

Чтобы лучше понять эти концепции, я пытаюсь проанализировать код, который используется клиентом программы измерения сети с открытым исходным кодом iPerf при отправке пакетов UDP для проверки таких параметров, как достижимая пропускная способность. Написано на C и C ++.

В частности, я попытался установить предлагаемое значение трафика намного выше, чем то, что может доставить сеть (и, следовательно, получатель), получив, как ожидается, определенную потерю пакета.

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

Тайм-аут также устанавливается один раз в сокет путем вызова:

setsockopt(mSettings->mSock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout))

Это должно установить тайм-аут отправки при записи в сокет, который, конечно, блокирует.

Когда буфер заполнен, вызов write () блокируется, и я вижу, как сильно увеличивается время цикла; проблема в том, что я не могу понять, на сколько времени этот вызов блокирует приложение. Вообще, когда write () заблокирован, он разблокируется так же, как есть место для нового пакета? Или он ждет больше (как это, кажется, происходит; насколько я смог понять, пытаясь установить «большое» значение буфера UDP (800 КБ, при отправке дейтаграммы UDP с полезной нагрузкой 1470 В), он, кажется, ждет в течение примерно 700 мс, позволяя опустошить буфер сетевым стеком, который непрерывно отправляет данные, для более чем места, которое потребовалось бы одному пакету)? Почему?

Другое сомнение, которое у меня есть, связано с тайм-аутом: я попытался внести небольшие изменения в исходный код, чтобы записать возвращаемое значение каждого вызова write (), и я смог заметить, что никаких ошибок никогда не обнаруживается, даже при установке тайм-аута 300 мс или 600 мс, что меньше значения, наблюдаемого ранее в 700 мс.

Записывая также эволюцию буфера (вместе с временем цикла при каждой передаче пакета), благодаря ioctl:

ioctl(mSettings->mSock,TIOCOUTQ,&bufsize);

Я смог заметить, однако, что установка времени ожидания на 300 мс или 600 мс действительно изменила ситуацию и заставила блокировку write () ждать около 300 мс, в первом случае, или 600 мс, в Второй случай, когда обнаружен полный буфер. Таким образом, хотя ошибок не обнаружено, время ожидания действительно истекает; это, однако, похоже, приводит к правильной операции записи во всех случаях.

Возможно ли это? Может ли это произойти, потому что write () заблокировал приложение на достаточное время, чтобы позволить ему полностью записать данные по истечении времени ожидания?

Я немного запутался по этому поводу.

Заранее большое спасибо.

...