сокет close () сразу после send (): unsafe? - PullRequest
26 голосов
/ 16 января 2012

Разумно ли / безопасно ли close() розетка сразу после последней send()?

Я знаю, что TCP должен пытаться доставить все оставшиеся данные в буфер отправки даже после закрытия сокета, но могу ли я действительно рассчитывать на это?

Я проверяю, что в моем приемном буфере не осталось никаких данных, чтобы после моего закрытия RST не отправлялось.


В моем случае закрытие - это фактически последний оператор кода перед вызовом exit().

Будет ли стек TCP продолжать пытаться передавать данные даже после завершения процесса отправки? Это так же надежно, как и ожидание произвольного тайм-аута перед вызовом close(), установив SO_LINGER?

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


Меня совсем не интересует уведомление о последнем отправленном байте; Я просто хочу, чтобы они в конечном итоге достигли удаленного хоста настолько надежно, насколько это возможно.

Подтверждения прикладного уровня не являются опцией (протокол HTTP, и я пишу небольшой сервер).

1 Ответ

23 голосов
/ 16 января 2012

Я много читаю конечную страницу SO_LINGER .Я рекомендую вам прочитать это тоже.В нем рассматриваются крайние случаи передачи больших данных в отношении сокетов TCP.

Я не эксперт в SO_LINGER, но на своем коде сервера (все еще в активной разработке) я делаю следующее:

  1. После отправки последнего байта с помощью send () я вызываю «shutdown (sock, SHUT_WR)», чтобы инициировать отправку FIN.

  2. Затем подождитедля последующего вызова recv () на этом сокете, чтобы вернуть 0 (или recv возвращает -1, а errno - это что-то иное, чем EAGAIN / EWOULDBLOCK).

  3. Затем сервер выполняет close ()на сокете.

Предполагается, что клиент сначала закроет свой сокет после получения всех байтов ответа.

Но у меня есть тайм-аутприменяется между последним send () и когда recv () указывает EOF.Если клиент никогда не закроет свой конец соединения, сервер все равно перестанет ждать и закроет соединение.У меня 45-90 секунд для этого тайм-аута.

Все мои сокеты не блокируются, и я использую poll / epoll, чтобы получать уведомления о событиях подключения в качестве подсказки, чтобы увидеть, не пора ли попробовать вызвать recv() или отправить () снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...