Как долго UDP-пакет остается в сокете? - PullRequest
14 голосов
/ 21 октября 2011

Если данные отправляются клиенту, но клиент занят выполнением чего-либо еще, как долго эти данные будут доступны для чтения с помощью recvfrom ()?

Кроме того, что произойдет, если второй пакет будет отправлен до того, как будет прочитан первый, потерян первый и следующий, сидящий там, ожидающий чтения?

(windows - udp)

Ответы [ 3 ]

15 голосов
/ 21 октября 2011

Если данные отправляются клиенту, но клиент занят выполнением чего-либо еще, как долго данные будут доступны для чтения с помощью recvfrom()?

Навсегда,или не совсем , или пока вы не закроете сокет или не прочитаете столько, сколько один байт.

Причина этого в следующем:
UDP доставляет дейтаграммы или не.Это звучит как бессмыслица, но это именно то, что есть.

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

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

Приемный буфер, очевидно, обязательно достаточно велик, чтобы вместить хотя бы одну дейтаграмму максимального размера (65535 байт), но, как правило, дейтаграммы будутне максимальный размер, а скорее что-то меньше 1280 байт (или 1500, если хотите), обычно он может содержать довольно много из них (на большинстве платформ буфер по умолчанию составляет около 128-256 КБ и настраивается).
Если в буфере недостаточно места, датаграмма отбрасывается, и вы получаете ничто (ну, вы делаете все еще получаете те, которые уже находятся в буфере).Опять же, вы даже не знаете, что что-то произошло.

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

Это очень отличается от того, как работает TCP.Здесь вы можете снова прочитать несколько байтов и несколько байтов, и это будет просто работать, потому что сетевой уровень имитирует поток данных .Вы даете дерьмо , как это работает, потому что сетевой стек гарантирует, что он работает.

Кроме того, что происходит, если второй пакет отправляется до того, как первый прочитан,первый потерян, а следующий сидит там в ожидании чтения?

Вы, вероятно, хотели сказать «получил», а не «отправил».Отправка и получение имеют разные буферы, так что это не имеет значения.О получении другого пакета, пока он еще находится в буфере, смотрите объяснение выше.Если в буфере может храниться вторая датаграмма, он сохранит ее, в противном случае он молча отправит * poof *.
Это не повлияет на любые дейтаграммы, уже находящиеся в буфере.

7 голосов
/ 21 октября 2011

Если данные отправляются клиенту, но клиент занят выполнением чего-либо еще, как долго эти данные будут доступны для чтения с помощью recvfrom ()?

Это зависит от ОС, в Windows, я полагаю, по умолчанию для каждого сокета UDP используется 8012, это можно поднять с помощью setsockopt () Документация Winsock Так что, пока буфер не заполнен , данные будут оставаться там до тех пор, пока сокет не будет закрыт или не будет прочитан.

Кроме того, что произойдет, если второй пакет будет отправлен до того, как будет прочитан первый, потерян первый и следующий, сидящий там, ожидающий чтения?

Если в буфере есть место, они оба сохраняются, если нет, один из них удаляется. Я считаю, что это самый новый, но я не уверен на 100%.

7 голосов
/ 21 октября 2011

Обычно данные буферизуются до тех пор, пока не будут прочитаны.Я полагаю, если вы подождете достаточно долго, чтобы в драйвере не хватило места, он должен будет сделать что-то , но при условии, что ваш код работает наполовину, это не должно быть проблемой.1004 * Типичный сетевой драйвер сможет буферизовать несколько пакетов без потери.

...