2016-02-03 5 views
2

В настоящее время я работаю над компилятором server + client на python, и я использую сокеты TCP. Из сетевых классов я знаю, что TCP-соединение должно быть закрыто шаг за шагом, сначала одна сторона посылает сигнал, что он хочет закрыть соединение и ждет подтверждения, а другая сторона делает то же самое. После этого гнездо можно безопасно закрыть.
Я видел в документации документации python socket.shutdown(flag), но я не вижу, как это можно было бы использовать в этом стандартном методе, теоретическом закрытии TCP-сокета. Насколько я знаю, он просто блокирует чтение, письмо или и то, и другое.
Какой лучший, самый правильный способ закрыть TCP-сокет в python? Существуют ли стандартные функции для закрытия сигналов или я должен сам их реализовать?Правильный способ закрытия сокетов tcp в python

+1

http://stackoverflow.com/questions/409783/socket -shutdown-против-сокетов близко – pigletfly

ответ

0

Согласно питона documentation, который говорит:

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

Я думаю, что самый правильный способ закрыть TCP-соединение - это использовать выключение перед закрытием соединения, потому что close не является атомарным! Это может привести к некоторым ошибкам. Предположим, вы используете функцию close без shutdown, и данные не отправлялись на сервер правильно, в то же время python закрывает соединение, и сервер не может ответить клиенту, теперь сокет на другом конце может зависать бесконечно.

0

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

Как правило, вы хотите закрыть полуканал TX, вызывая выключение (1). На уровне TCP он отправляет пакет FIN, а удаленный конец получает 0 байтов, если блокирует чтение(), но удаленный конец все равно может отправить данные обратно, поскольку полуканат RX все еще открыт.

Некоторые протоколы приложений используют это, чтобы сигнализировать о завершении сообщения. Некоторые другие протоколы обнаруживают МНВ на основе самих данных. Например, в интерактивном протоколе (где сообщения обмениваются много раз), возможно, не будет возможности или необходимости закрыть половинный канал.

В HTTP, shutdown (1) - это один из методов, который клиент может использовать для оповещения о завершении HTTP-запроса. Но сам протокол HTTP включает данные, которые позволяют определить, где заканчивается запрос, поэтому HTTP-соединения с несколькими запросами все еще возможны.

Я не думаю, что вызов shutdown() перед закрытием() всегда необходим, если только вам не нужно явно закрывать половину канала. Если вы хотите прекратить все общение, закройте() это тоже. Вызов shutdown() и забывание вызвать close() хуже, потому что ресурсы дескриптора файла не освобождаются.

Из Википедии: «В системах SVR4 использование функции close() может отбрасывать данные. Для обеспечения доставки всех данных в этих системах может потребоваться использование shutdown() или SO_LINGER.«Это означает, что если у вас есть выдающиеся данные в выходном буфере, close() может немедленно удалить эти данные в системе SVR4. Системы на базе Linux, BSD и BSD, такие как Apple, не являются SVR4, а будет попытаться отправить(). Я не уверен, что в настоящее время какой-либо крупный коммерческий UNIX по-прежнему является SVR4.

Опять же, используя HTTP как пример, HTTP-клиент, работающий на SVR4, не потеряет данные, используя close(), потому что он будет поддерживать соединение открытым после запроса, чтобы получить ответ. HTTP-сервер под SVR должен быть более осторожным, вызывая shutdown (2) перед закрытием() после отправки всего ответа, поскольку ответ будет частично в выходном буфере .

Смежные вопросы