Я считаю, что на этот вопрос лучше всего ответить с точки зрения сетевого взаимодействия с Linux, а не с языком go, поскольку серверу go для прослушивания сокета потребуется выполнить следующее:
Я описываю случай для TCP-сервера, но UDP-сервер будет аналогичным (в определенной степени!). Вы можете исследовать его самостоятельно, настроив простой сервер и запустив его с помощью strace, например:
strace -e trace=network nc -l -s 192.168.0.1 7777
(часть strace
будет отображать системные вызовы, а часть nc -l
будет прослушивать данный адрес)
Вывод (я советую вам попробовать нечто подобное на простом go-сервере!):
bind(3, {sa_family=AF_INET, sin_port=htons(7777), sin_addr=inet_addr("192.168.0.1")}, 16) = 0
listen(3, 1) = 0
accept4(3,
Мы видим, что сервер блокирует входящий вызов и ожидает входящих соединений. То, что здесь происходит, более точно указано в справочных страницах Linux:
Если в очереди нет ожидающих соединений, а сокет
не помеченный как неблокирующий, accept () блокирует вызывающего до
связь присутствует. Если розетка помечена как неблокирующая и нет
ожидающие соединения присутствуют в очереди, accept () завершается неудачно с
ошибка EAGAIN или EWOULDBLOCK.
Теперь вопрос в том, как пакет, полученный интерфейсом хоста, попадает в этот сокет. Он должен пройти через стек TCP / IP и, наконец, попасть в наше приложение. Это не тривиальный процесс, и вы можете найти подробности о нем во многих руководствах по работе с сетями Linux ). По сути, происходит следующее (это ОЧЕНЬ ВЫСОКИЙ уровень описания / обобщения):
- Пакет поступает на сетевую карту, классифицируется и
достигает правильного верхнего уровня (например, IP в случае пакетов IP)
- Пакет поступает на уровень IP, где заголовок IP проверяется среди
другие вещи, а затем заголовок IP удаляется и пакет
переносимый этим IP-пакетом передается на верхний уровень (например, в случае
TCP - на уровень TCP)
tcp_v4_rcv
функция вызывается с уровня IP (в случае TCPv4),
и пакет прибывает на уровень TCP. Здесь заголовок проверен и
затем ищется открытый сокет для этого входящего пакета
(звоните __tcp_v4_lookup
).
На этом этапе, если сокет TCP для этого пакета не найден, пакет отбрасывается. В противном случае упакованный пакет передается процессу.
Чтобы прямо ответить на ваш вопрос: если IP-адрес изменяется, и старый сокет TCP был привязан к старому IP-адресу, пакет, полученный для этого сокета (который все еще будет открыт, если сервер работает и не обновляется), будет быть отброшенным где-нибудь в пути через сетевые части ядра Linux.
Вот
Если вы действительно хотите углубиться в подробности, хорошее описание того, что происходит, можно найти в отличной статье Внутри Linux Packet Filter (и part 2 о том, что происходит над уровнем IP )