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