Какое значение возвратит recv (), если получит действительный пакет TCP с размером полезной нагрузки 0 - PullRequest
5 голосов
/ 07 июля 2010

При программировании сокета TCP, если recv() возвращает 0, это считается признаком того, что другая сторона закрыла соединение. Однако, AFAIK, TCP RFC не требует, чтобы полезная нагрузка TCP была> 0. Таким образом, теоретически стек TCP может получать сообщение с полезной нагрузкой 0.

Итак, по сути, мой вопрос: что вернет recv(), если получит пакет с полезной нагрузкой размером 0? Если он возвращает 0, то как мы можем отличить его от индикации закрытого соединения.

Ответы [ 2 ]

11 голосов
/ 08 июля 2010

Сегменты TCP с размером полезной нагрузки 0 являются вездесущими - они встречаются практически во всех реальных потоках TCP.Они отправляются всякий раз, когда одна сторона желает подтвердить получение данных от другой, но не имеет собственных данных для отправки.(Они обычно известны как «пакеты ACK», но «пакет ACK» - это обычный сегмент, в котором отсутствуют данные).

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

Помните, что TCP ориентирован на поток: существует , а не отображение 1: 1 между данными, возвращаемыми одним вызовом recv(), и данными в одном сегменте TCP.Один вызов recv() может вернуть блок данных, который перекрывает несколько сегментов TCP, а данные в одном сегменте TCP могут быть возвращены в нескольких вызовах recv().Границы между сегментами TCP не видны приложению с помощью API сокетов BSD.Если вам нужны такие границы, вам нужно либо реализовать себя, используя протокол уровня приложения в потоке TCP, либо использовать протокол, ориентированный на дейтаграммы, такой как UDP.

3 голосов
/ 08 июля 2010

Правильно, согласно POSIX, если recv возвращает 0, то одноранговое соединение корректно завершает соединение.

Если кому-то удалось отправить пакет TCP с полезной нагрузкой нулевого размера,тогда ОС не должна возвращать какие-либо данные в процесс, блокируемый системным вызовом recv на этом сокете.

Помните, что полезные данные TCP образуют непрерывный поток, который может быть случайным образомсрезанный ОС, а не последовательность дейтаграмм, которые должны быть возвращены во время одного системного вызова.

...