如果绑定到特定接口然后IP发生变化,会发生什么情况?

时间:2018-07-06 11:13:39

标签: linux go network-programming

使用以下代码片段,我将绑定到特定接口

iface, err := net.InterfaceByName(ifaceName)

if err != nil {
    return nil, fmt.Errorf("ERR: Error using interface %q: %q", ifaceName, err.Error())
}

addrs, err := iface.Addrs()

if err != nil {
    return nil, fmt.Errorf("ERR: Error using interface %q: %q", ifaceName, err.Error())
}

if len(addrs) < 1 {
    return nil, fmt.Errorf("ERR: Interface %q has no addresses?", ifaceName)
}

ipAddr := addrs[0].(*net.IPNet).IP
udpAddr := &net.UDPAddr { IP: ipAddr }

,然后将其用作侦听的本地地址。是否有人知道如果接口的IP地址更改会发生什么情况?

1 个答案:

答案 0 :(得分:5)

我认为这是一个关于linux网络的最佳回答,而不是那么多的go语言,因为go服务器将必须执行以下操作才能监听套接字:

我描述了TCP服务器的情况,但是UDP服务器将是类似的(在一定程度上!)。您可以通过设置一个简单的服务器并使用strace运行它来自己进行调查,例如:

strace -e trace=network nc -l -s 192.168.0.1 7777strace部分将显示系统调用,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 stack,最后到达我们的应用程序。这不是一个微不足道的过程,您可以在许多linux networking guides中找到有关它的详细信息。本质上,会发生什么(这是非常高级的描述/概括):

    数据包到达网络接口卡,被分类并 到达正确的上层(例如,在IP数据包的情况下为IP) 包到达IP层,在其中检查IP标头 其他事情,然后剥离IP报头,将数据包 该IP数据包携带的数据会传递到上层(例如 TCP-到TCP层) 从IP层调用
  1. tcp_v4_rcv函数(对于TCPv4), 数据包到达TCP层。在这里,检查标头, 然后寻找此传入数据包的开放套接字 (致电__tcp_v4_lookup)。

在此阶段,如果找不到此数据包的TCP套接字,则将丢弃该数据包。否则,将其打包传递给进程。

直接回答您的问题:如果IP地址更改,并且旧的TCP套接字已绑定到旧的IP地址,则此套接字收到的数据包(如果服务器正在运行且未刷新,它将仍然打开)在整个Linux内核的网络连接过程中被丢弃。

这是一个 如果您真的想更深入,可以在一篇很棒的文章Inside the Linux Packet Filter(以及part 2中有关IP层之上发生的事情)中找到关于发生的事情的很好的描述