Подтвердить что ты не робот

Socket.shutdown vs socket.close

Недавно я увидел немного кода, который выглядел бы так (с носком, являющимся объектом сокета, конечно):

sock.shutdown(socket.SHUT_RDWR)
sock.close()

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

4b9b3361

Ответ 1

Здесь описывается :

Как только сокет больше не требуется, вызывающая программа может отменить сокет, применяя закрытую подпрограмму к дескриптору сокета. Если надежная розетка для доставки данных связанный с ним, когда закрывается место, система продолжает пытаться Обмен данными. Однако, если данные все еще не освобожден, система отбрасывает данные. Если приложение программа не предназначена для любых ожидающих данных, он может использовать выключение подпрограммы на разъеме до закрывая его.

Ответ 2

Вызов close и shutdown имеет два разных эффекта на базовый сокет.

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

Когда вы вызываете close, он уменьшает счетчик дескрипторов на единицу, и если количество совпадений достигло нуля, сокет и связанное с ним соединение проходят через обычную процедуру закрытия (фактически отправляя FIN/EOF в одноранговую сеть) и сокет освобождается.

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

С другой стороны, вызов shutdown для чтения и записи закрывает базовое соединение и отправляет FIN/EOF партнеру независимо от того, сколько процессов имеет дескрипторы сокета. Тем не менее, не освобождает сокет, и вам все равно нужно позвонить после этого.

Ответ 3

Объяснение выключения и закрытия: Изящное завершение (msdn)

Выключение (в вашем случае) указывает на другой конец соединения, нет никакого другого намерения читать или записывать в сокет. Затем закроет любую память, связанную с сокетом.

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

IMO "shutdown" и "close" имен вводят в заблуждение, "close" и "destroy" будут подчеркивать их различия.

Ответ 4

он упоминается прямо в Socket Programming HOWTO (py2/py3)

Разъединение

Строго говоря, вы должны использовать shutdown в сокете, прежде чем вы close его. shutdown является советом для сокета на другом конце. В зависимости от аргумента, который вы передаете, это может означать, что "я больше не буду отправлять, но я все еще слушаю", или "Я не слушаю, хорошее избавление!". Однако большинство библиотек сокетов используются для программистов, не обращая внимания на использование этой этикетки, которая обычно close совпадает с shutdown(); close(). Поэтому в большинстве ситуаций явное закрытие не требуется.

...

Ответ 6

Является ли этот код неправильным?

Закрытие вызова сразу после выключения может заставить ядро ​​отказаться от всех исходящих буферов.

Согласно http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable нужно подождать между выключением и закрытием до тех пор, пока чтение не вернет 0.

Ответ 7

Выключение (1), заставляет сокет no отправлять больше данных

Это полезно в

1- промывка буфера

2- Незначительное обнаружение ошибок

3- Безопасная охрана

Позвольте мне объяснить больше, когда вы отправляете данные от A до B, это не гарантируется отправленный в B, он гарантированно будет отправлен в буфер A os, который, в свою очередь, отправляет его в буфер B os

Таким образом, вызывая shutdown (1) на A, вы очищаете буфер и возникает ошибка если буфер не пуст, т.е. данные еще не отправлены равноправному узлу

Однако это невозможно, поэтому вы можете сделать это после того, как вы полностью отправил все ваши данные, и вы хотите быть уверены, что он по крайней мере на равных os buffer