Что происходит с сеансом TCP при изменении IP-адреса клиента?
Я провел простой тест: netcat прослушивает порт и подключается к этому порту с клиентской машины. Затем я изменил IP-адрес клиента, пока этот сеанс nc был открыт, и отправил некоторые данные, после изменения IP-адреса сервер не получил никаких данных.
Насколько я понимаю, сокет TCP состоит из номера порта IP +, поэтому изменение IP разрывает это соединение. nc не имеет возможности узнать, что IP-адрес изменился, поэтому он продолжает отправлять данные на исходный IP-адрес до истечения времени ожидания сеанса.
Видеть RFC 793 (Протокол управления передачей), в частности раздел 2.7:
2.7. Установление и отключение соединения
Чтобы идентифицировать отдельные потоки данных, которые может обрабатывать TCP, TCP предоставляет идентификатор порта. Поскольку идентификаторы портов выбираются каждым TCP независимо, они могут не быть уникальными. Чтобы обеспечить уникальные адреса внутри каждого TCP, мы объединяем интернет-адрес, идентифицирующий TCP, с идентификатором порта, чтобы создать сокет, который будет уникальным для всех сетей, соединенных вместе.
Я предлагаю использовать Wireshark или другой сниффер пакетов, чтобы самостоятельно наблюдать за трафиком и видеть его в действии.
Предыдущие ответы скажут вам, что TCP-соединения не могут поддерживаться при изменении IP-адреса. Так было в 2009 году, когда были написаны эти ответы.
Однако в январе 2013 г. RFC 6824 был опубликован, что представляет способ поддержания активности TCP-соединений при изменении IP-адреса. По состоянию на июнь 2014 года он еще не получил широкой поддержки. В частности, эталонная реализация существует как патч для Linux, а iOS7 по умолчанию поддерживает MPTCP. Википедия перечисляет всего пять реализаций.
Другие ответили с точки зрения соединения, идентифицируемого парой IP + Port. Позвольте мне немного рассказать о том, как это работает в слоистой структуре.
TCP - это уровень, который обеспечивает «иллюзию» надежного потока поверх ненадежного уровня пакетов (IP). Для этого он должен учитывать несколько переменных для управления потоком, а также должен предоставлять соответствующие параметры для уровня ниже.
Итак, когда вы просите TCP открыть поток, вы даете ему IP + порт назначения. Он сохраняет этот IP-номер и каждый раз, когда ему нужно что-то передать, собирает IP-пакет и сообщает IP-уровню, чтобы он отправил его на предполагаемую машину, идентифицируемую только по исходному IP-номеру.
Когда вы меняете IP-адрес одной машины, TCP-уровень другой не имеет возможности узнать, что произошло. Он видит только то, что на любой IP-пакет, отправленный на исходный IP-номер, больше не отвечает (возможно, он получает сообщение ICMP о том, что нет машины с этим IP-номером). Кроме того, он больше не получает пакетов с этим IP-номером. Очевидно, соединение будет разорвано по истечении некоторого времени ожидания.
Хуже того, он может начать получать некоторые несвязанные пакеты из другого источника (новый IP-номер), но они предполагают, что соединение уже установлено! Конечно, единственный ответ, который машина может получить (если вообще получит), - это RST-пакет, который заставит его немедленно прекратить работу и прекратить выполнение.
Сессия умрет. Сокеты TCP: dst-порт, dst-ip, src-порт, src-ip. Если что-то из этого изменится, соединение должно быть разорвано (по крайней мере, согласно Стивенсу).
EDIT: это верно для любой реализации, соответствующей RFC. RFC 793, раздел 2.7
Сеансы TCP идентифицируются IP-адресом и номером порта на обеих сторонах соединения. Изменение IP-адреса на одной стороне нарушит этот сеанс.
Комбинация (адрес источника, порт источника, адрес назначения, порт назначения) называется пара розеток. Он используется стеком TCP для идентификации соединения. После того, как он установлен, TCP не имеет возможности обновить что-либо из них.
SCTP позволяет конечным точкам менять свои адреса на лету, но широко не используется (во всяком случае, пока).