первичный дизайн цели TCP является, чтобы позволить надежную передачу данных в условиях потери пакетов, пакетов переназначения и — ключа, здесь дублирования — пакетов.
Довольно очевидно, что сетевой стек TCP/IP имеет дело со всем этим, пока соединение завершено, но есть крайний случай, который происходит сразу после закрытия соединения. Что произойдет, если пакет, отправленный в конце разговора, дублируется и задерживается, так что пакеты the 4-way shutdown добираются до получателя до отложенного пакета? Стек аккуратно закрывает соединение. Затем появляется всплывающий дублированный пакет. Что должен делать стек?
Что еще более важно, что делать, если программа, которая принадлежала этому соединению, сразу же умирает, а затем запускает один и тот же IP-адрес и номер порта TCP?
Есть несколько вариантов:
повторное Disallow этого комбо IP/порт, по крайней мере, в 2 раза максимальное время пакет может находиться в полете. В TCP это обычно называют задержкой 2 × MSL. Иногда вы также видите 2 × RTT, что примерно эквивалентно.
Это поведение по умолчанию для всех распространенных стеков TCP/IP. 2 × MSL обычно составляет от 30 до 120 секунд. (Это период TIME_WAIT
.) После этого времени стек предполагает, что все пакеты-изгои были опущены по маршруту из-за истекшего TTLs, поэтому он оставляет состояние TIME_WAIT
, позволяя повторному использованию этой комбинации IP/port.
Позволяет новой программе повторно привязываться к этой комбинации IP/port.В пакетах с BSD sockets интерфейсами — по существу все Unix и Unix-подобные системы, а также Windows через Winsock —, вы должны попросить об этом, установив опцию SO_REUSEADDR
через setsockopt()
, прежде чем позвонить по телефону bind()
.
SO_REUSEADDR
чаще всего устанавливается в серверных программах.
Причина в том, что вы изменяете конфигурационный файл сервера и должны перезапустить этот сервер, чтобы перезагрузить его конфигурацию. Без SO_REUSEADDR
вызов bind()
в новом экземпляре новой программы перезапустится, если были открыты соединения с предыдущим экземпляром, когда вы его убили. Эти соединения будут удерживать порт TCP в состоянии TIME_WAIT
в течение 30-120 секунд, поэтому вы попадете в случай 1 выше.
Безопасная вещь - это подождать TIME_WAIT
, но на практике это не очень большой риск того, что это стоит того. Лучше сразу вернуть сервер обратно, чтобы не пропустить больше входящих соединений, чем необходимо.
Я не понимаю, почему этот вопрос отмечен vC++ ... –
Ошибка. Я имел ввиду C++. Спасибо. –
Это все еще не имеет ничего общего с C++ :) –