socket.shutdown против socket.close

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

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

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

7 ответов

Решение

Вот одно объяснение:

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

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

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

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

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

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

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

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

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

IMO названия "выключение" и "закрытие" вводят в заблуждение, "закрытие" и "уничтожение" подчеркивают их различия.

Это упоминается прямо в HOWTO по программированию сокетов ( py2/ py3)

Отсоединение

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

...

Разве этот код выше не так?

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

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

Есть несколько вариантов завершения работы: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.shutdown.aspx. * nix похож.

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

Это полезно в

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

2- Странное обнаружение ошибок

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

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

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

Как бы то ни было, это необратимо, так что вы можете сделать это после того, как полностью отправили все свои данные и хотите быть уверены, что они как минимум в буфере peer os

Другие вопросы по тегам