Причина не правильно закрытой розетки? - PullRequest
1 голос
/ 11 апреля 2010

Вот что я пытаюсь сделать: Сервер отправляет сообщение подключенным клиентам, когда появляются новые сообщения. Клиент, с другой стороны, при подключении пытается отправить сообщение на сервер с помощью send (), а затем получить сообщение с помощью recv (), сразу после этого клиент вызывает close (), чтобы закрыть соединение.

Иногда, после того как клиент завершает работу, сервер пытается получить сообщение от клиента, что приводит к ошибке 104 - «сброс соединения по одноранговой сети». Когда это происходит, Wireshark обнаруживает, что последние два сегмента, отправленные клиентом:
1. ACK, подтверждающий получение сообщения, отправленного сервером
2. RST / ACK
FIN не отправляется клиентом.

Почему это происходит и как я могу "правильно" закрыть сокет на клиенте?

1 Ответ

1 голос
/ 12 апреля 2010

Это произойдет, если вы вызовете close() на клиенте, данные которого еще находятся в очереди приема. Клиент будет отправлять RST вместо FIN, что указывает на то, что не все данные были успешно доставлены в приложение. Если соединение было только в интересах клиента, то, вероятно, серверу это безразлично; поскольку дальнейшая связь по этому сокету невозможна, сервер должен просто закрыть его.

Этого можно избежать, отключив соединение следующим образом (где A - сторона, инициирующая отключение):

  • Когда А завершает отправку всех данных, он вызывает shutdown(sock, SHUT_WR) и продолжает чтение из сокета.
  • Когда B видит EOF (например, recv() возвращает 0), он знает, что A инициирует отключение. B отправляет любые окончательные ответы или другие окончательные данные в зависимости от обстоятельств, звонит shutdown(sock, SHUT_WR), а затем close(sock).
  • Когда A видит EOF, если он уже выключен, пишет, он просто вызывает close(sock).

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

...