Какое значение возвратит recv(), если получит действительный пакет TCP с размером полезной нагрузки 0
В программировании сокетов TCP, если recv()
возвращает 0, это принимается как признак того, что другая сторона закрыла свое соединение. Однако, AFAIK, TCP RFC не требует, чтобы полезная нагрузка TCP была> 0. Таким образом, теоретически стек TCP может получать сообщение с полезной нагрузкой 0.
Итак, по сути мой вопрос, что будет recv()
возвращает, если получает пакет полезной нагрузки размером 0? Если он возвращает 0, то как мы можем отличить его от индикации закрытого соединения.
2 ответа
Сегменты TCP с размером полезной нагрузки 0 распространены повсеместно - они встречаются практически во всех реальных потоках TCP. Они отправляются всякий раз, когда одна сторона желает подтвердить получение данных от другой, но не имеет собственных данных для отправки. (Они обычно известны как "пакеты ACK", но "пакет ACK" - это обычный сегмент, в котором нет данных).
Поскольку такие пакеты не содержат никаких данных для доставки пользователю приложения, они не будут вызывать recv()
возвращать - recv()
будет продолжать блокировку до тех пор, пока не будут получены некоторые фактические данные. Если recv()
возвращает 0, тогда это явный признак того, что другой конец закрыл свою сторону соединения и больше не будет отправлять данные.
Помните, что TCP ориентирован на поток: не существует взаимно-однозначного соответствия между данными, возвращаемыми одним recv()
вызов и данные в одном сегменте TCP. Один recv()
Вызов может вернуть блок данных, который перекрывает несколько сегментов TCP, и данные в одном сегменте TCP могут быть возвращены в нескольких recv()
звонки. Границы между сегментами TCP не видны приложению с помощью API сокетов BSD. Если вам нужны такие границы, вам нужно либо реализовать себя, используя протокол прикладного уровня в потоке TCP, либо использовать протокол, ориентированный на дейтаграммы, такой как UDP.
Правильно, согласно POSIX, если recv
возвращается 0
затем соединение корректно закрывается одноранговым узлом.
Если кому-то удалось отправить TCP-пакет с полезной нагрузкой нулевого размера, то ОС не должна возвращать какие-либо данные в процесс, который блокируется. recv
Системный вызов на этом сокете.
Помните, что полезные нагрузки TCP образуют непрерывный поток, который может быть случайно разрезан ОС, а не последовательность дейтаграмм, которые должны быть возвращены во время одного системного вызова.