Закрытие TCP-сокета с обеих сторон оставляет живую розетку [дубликат]

Вы могли бы сделать ...

#define replace replacement
#define to here

Следите за непреднамеренными побочными эффектами определений. Вероятно, вы захотите #undef их после того, как они выполнили свою работу.

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

3 ответа

Стороной, которая была инициирована закрытие соединения, является та, которая заканчивается в состоянии 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-адреса на сервере.
  • Вероятно, лучший вариант, если это выполнимо: отредактируйте свой протокол, чтобы завершившиеся соединения не были закрыты, но клиент должен выбрать один для подключения к нему (round robin, random и т. Д.). перейдите в «незанятое» состояние, чтобы их можно было повторно использовать позже, вместо того, чтобы открывать новое соединение (например, HTTP keep-alive).
6
ответ дан caf 19 August 2018 в 08:57
поделиться
  • 1
    Извините, что прокомментировал старый вопрос, но не должен в первом абзаце этого ответа читать «сторона, в которой ИНИЦИИРОВАЕТ закрытие соединения, это тот, который заканчивается в состоянии TIME_WAIT». ? Кажется, я помню, что прочитал, что в какой-то книге, а также, похоже, что подразумевается в hea-www.harvard.edu/~fine/Tech/addrinuse.html – zentrunix 6 August 2013 в 16:43
  • 2
    @ JoséX: Да, ты прав. – caf 6 August 2013 в 23:39

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

1
ответ дан Richard Pennington 19 August 2018 в 08:57
поделиться
  • 1
    Сожалею. Я забыл добавить, что я устанавливаю SO_REUSEADDR. См. В статье, что он не предотвращает ошибки использования Адреса при подключении к одному и тому же порту / хосту. – richcollins 18 December 2009 в 23:37

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

0
ответ дан Wheezil 19 August 2018 в 08:57
поделиться
Другие вопросы по тегам:

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