Поделиться через


Корректное завершение работы, параметры Linger и закрытие сокета

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

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

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

В сокетах Windows функция завершения работыи функция WSASEndDisconnectможно использовать для запуска последовательности завершения работы, а функция закрытияиспользуется для освобождения дескрипторов сокетов и освобождения всех связанных ресурсов. Однако возникает некоторая путаница из-за того, что функция закрыть неявно приводит к возникновению последовательности завершения работы, если она еще не произошла. На самом деле, это довольно распространенная практика программирования для использования этой функции и использования closesocket для запуска последовательности завершения работы и освобождения дескриптора сокета.

Чтобы упростить это использование, интерфейс сокетов предоставляет элементы управления путем механизма параметра сокета, который позволяет программисту указывать, должна ли неявная последовательность завершения работы быть корректной или прерванной, а также следует ли выполнять функцию closesocket (которая не завершена немедленно), чтобы разрешить время для правильной последовательности завершения работы. Эти важные различия и последствия использования closesocket по-прежнему не понимаются широко.

Установив соответствующие значения для параметров сокета SO_LINGER и SO_DONTLINGER, можно получить следующие типы поведения с помощью функции closesocket:

  • Прерванная последовательность завершения работы, немедленный возврат из closesocket.
  • Правильное завершение работы, задержка возврата до завершения последовательности завершения работы или указанного интервала времени истекает. Если срок действия истекает до завершения правильной последовательности завершения работы, возникает прерванная последовательность завершения работы, а закрыть возвращается.
  • Корректное завершение работы, немедленное возвращение— что позволяет завершить последовательность завершения работы в фоновом режиме. Хотя это поведение по умолчанию, приложение не может знать, когда (или ли) грациозная последовательность завершения работы фактически завершается.

Использование параметров сокета SO_LINGER и SO_DONTLINGER и связанной структуры подробно рассматривается в справочных разделах о параметрах сокетаSOL_SOCKET и структуре.

Один из способов, которые можно использовать для минимизации вероятности возникновения проблем во время отключения подключения, заключается в том, чтобы избежать неявного завершения работы, инициированного closesocket. Вместо этого используйте одну из двух явных функций завершения работы, завершения работы или WSASendDisconnect. Это, в свою очередь, приводит к получению FD_CLOSE указания одноранговым приложением, указывающее, что все ожидающие данные были получены. Чтобы проиллюстрировать это, в следующей таблице показаны функции, которые будут вызываться клиентскими и серверными компонентами приложения, где клиент несет ответственность за инициирование корректного завершения работы.

Клиентская сторона Серверная сторона
(1) Вызывает завершения работы(SD_SEND), чтобы сигнализировать о завершении сеанса, и этот клиент больше не имеет данных для отправки.
(2) Получает FD_CLOSE, указывая на правильное завершение работы и получение всех данных.
(3) Отправляет все оставшиеся данные ответа.
(только локальное значение времени) Возвращает FD_READ и вызовы для получения любых данных ответа, отправляемых сервером. (4) Вызывает завершения работы(SD_SEND) для указания, что сервер больше не имеет данных для отправки.
(5) Получает FD_CLOSE указание. (только локальное значение времени) Вызывает closesocket.
(6) Вызывает closesocket.