Избегать TIME_WAIT - PullRequest
       12

Избегать TIME_WAIT

6 голосов
/ 19 декабря 2009

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

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

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

Ответы [ 3 ]

6 голосов
/ 19 декабря 2009

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

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

Поскольку в вашем сценарии зафиксированы три части этого кортежа (server host, server port, client host), у вас действительно есть только эти опции:

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

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

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

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

1 голос
/ 19 декабря 2009

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

0 голосов
/ 14 мая 2013

Установка SO_REUSEADDR на стороне клиента не помогает на стороне сервера, если только она также не устанавливает SO_REUSEADDR

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