Поведение выключения (sock, SHUT_RD) с TCP - PullRequest
9 голосов
/ 12 апреля 2009

При использовании сокета TCP, что делает

shutdown(sock, SHUT_RD);

на самом деле? Это просто заставляет все recv() звонки возвращать код ошибки? Если да, то какой код ошибки?

Вызывает ли это посылку каких-либо пакетов базовым TCP-соединением? Что происходит с любыми данными, которые отправляет другая сторона в этот момент, - сохраняется ли оно, и размер окна соединения продолжает уменьшаться, пока не достигнет 0, или оно просто отбрасывается, а размер окна не уменьшается? *

Ответы [ 6 ]

4 голосов
/ 24 октября 2009

Отключение стороны чтения сокета приведет к тому, что любые заблокированные вызовы recv (или аналогичные) вернут 0 (что означает постепенное отключение). Я не знаю, что будет с данными, которые в настоящее время перемещаются вверх по стеку IP. Это наверняка будет игнорировать данные, которые находятся в полете с другой стороны. Это никак не повлияет на запись в этот сокет.

На самом деле, разумное использование shutdown - это хороший способ убедиться, что вы убираете, как только закончите. HTTP-клиент, который не использует keepalive, может отключить сторону записи, как только он завершит отправку запроса, и сервер, который видит Connection: closed, может аналогичным образом отключить сторону чтения, как только он завершит прием запроса. Это приведет к тому, что любая дальнейшая ошибочная активность будет сразу очевидна, что очень полезно при написании кода уровня протокола.

3 голосов
/ 26 октября 2010

shutdown (, SHUT_RD) не имеет никакого аналога в протоколе TCP, поэтому очень важно реализовать, как вести себя, когда кто-то пишет в соединение, где другая сторона указала, что оно не будет читать, или когда вы пытаетесь читать после Вы заявили, что не будете.

На немного более низком уровне полезно помнить, что TCP-соединение представляет собой пару потоков, с помощью которых одноранговые узлы отправляют данные до тех пор, пока они не объявят о своем завершении (SHUT_WR, который отправляет FIN). И эти два потока совершенно независимы.

3 голосов
/ 12 апреля 2009

Глядя на исходный код Linux, shutdown(sock, SHUT_RD), похоже, не вызывает никаких изменений состояния сокета. (Очевидно, shutdown(sock, SHUT_WR) приводит к установке FIN.)

Я не могу комментировать изменения размера окна (или их отсутствие). Но вы можете написать тестовую программу, чтобы увидеть. Просто включите inetd службу chargen и подключитесь к ней. : -)

1 голос
/ 21 марта 2014

Я тестирую shudown(sock,SHUT_RD) в Ubuntu 12.04. Я обнаружил, что при вызове shutdown(sock,SHUT_RD), если в буфере TCP нет данных какого-либо типа (включая FIN ....), последующий вызов чтения будет return 0 (указывает на конец потока). Но если есть какие-то данные, поступившие до или после функции выключения, вызов read будет обрабатываться нормально, как если бы функция выключения не вызывалась. Похоже, что shutdown(sock,SHUT_RD) не вызывает изменения каких-либо состояний TCP на сокет

0 голосов
/ 09 февраля 2014

Имеет два эффекта, один из которых зависит от платформы.

  1. recv () вернет ноль, указывая конец потока.
  2. Любые дальнейшие записи в соединение со стороны однорангового узла будут либо (а) тихо выброшены получателем (BSD), (b) будут буферизованы получателем и в конечном итоге приведут к тому, что send () заблокирует или вернет -1 / EAGAIN / EWOULDBLOCK (Linux) или (c) заставить получателя отправить RST (Windows).
0 голосов
/ 24 октября 2009

shutdown (sock, SHUT_RD) заставляет любого записывающего устройства в сокет получать сигнал sigpipe.

Любое дальнейшее чтение с использованием системного вызова read возвращает -1 и устанавливает errno на EINVAL.

Использование recv вернет -1 и установит errno для обозначения ошибки (возможно, ENOTCONN или ENOTSOCK).

...