Корректное завершение работы, параметры 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. |