Предотвращение TIME_WAIT

Я стараюсь избегать TIME_WAIT в клиенте. Я соединяю и затем устанавливаю O_NONBLOCK и SO_REUSEADDR. Я называю чтение, пока оно не возвращается 0. Когда считанные возвраты 0, errno также 0. Я интерпретировал это как знак, что сервер закрыл соединение. Однако, если я звоню близко, сокет установлен на TIME_WAIT, как подтверждено netstat.

Так как я устанавливаю много связей с тем же хостом / порт, я в конечном счете начинаю видеть, "Исправляют используемые" ошибки (см. http://hea-www.harvard.edu/~fine/Tech/addrinuse.html).

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

6
задан richcollins 18 December 2009 в 22:36
поделиться

2 ответа

Сторона, которая инициировала закрытие соединения, оказывается в состоянии TIME_WAIT . read () , возвращающий 0, должен указывать на то, что сервер первым закрыл сокет, поэтому да - это должно означать, что TIME_WAIT заканчивается на стороне сервера, и клиент проходит через LAST_ACK .

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

Поскольку три части этого кортежа фиксированы в вашем сценарии ( хост сервера , порт сервера , клиентский хост ), у вас действительно есть только следующие параметры:

  • Попробуйте сделать больше клиентских портов доступными. Некоторые операционные системы по умолчанию используют только небольшой диапазон доступных портов для «эфемерных портов» (я не уверен насчет OSX в этом отношении). Если это так, посмотрите, можете ли вы изменить диапазон с помощью настройки конфигурации в ОС или, в качестве альтернативы, попросите приложение искать рабочий порт с помощью bind () / connect () в цикле, пока соединение не сработает.

  • Увеличьте количество доступных значений хоста клиента , используя несколько IP-адресов на вашем клиенте. Однако вам потребуется приложение bind () специально для одного из этих IP-адресов.

  • Увеличьте количество доступных значений хоста сервера / порта сервера , используя несколько портов и / или IP-адресов на сервере. Клиенту нужно будет выбрать один из них для подключения (циклический, случайный и т. Д.).

  • Вероятно, лучший вариант, если это выполнимо: рефакторинг вашего протокола, чтобы завершенные соединения не закрывались, а переходили в " состояние простоя, чтобы их можно было повторно использовать позже, вместо открытия нового соединения (например, HTTP keep-alive).

6
ответ дан 17 December 2019 в 00:10
поделиться

Позже на той же странице упоминается SO_REUSEADDR. Вот что тебе нужно. Вы определенно захотите закрыть дескриптор прочитанного файла, когда он вернет ноль.

1
ответ дан 17 December 2019 в 00:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: