网卡与端口复用
前言
前几天有一个需求,要做一个监控udp组播数据是否正常发送的项目, 需要监控多路组播数据,且要部署在多台机器上,且每台机器发送的数据类型有两种,为了监控是哪种数据类型出问题了,因此在发送数据时,需要绑定网卡,监控程序同时绑定对应网卡,监控对应类型的数据。
正文
监控程序很快就写好了,但是在做测试的时候发现,部署在同一台机器上,绑定不同网卡的程序,在只有一块网卡发送数据时,两个程序居然都能收到数据(其中一个程序绑定的是另一块网卡,而另一块网卡并没有工作),在down掉工作的网卡后,两个监控程序都收不到数据了。
正常来说,理想情况是,只有一块网卡工作时,绑定另一块网卡的监控程序应该是收不到数据的,down掉这块网卡后,绑定对应网卡的监控程序应该收不到数据,但现实很骨感。
在排除各种情况之后,经过与同事的讨论,最终我们认为问题出现在端口复用上,两个监控程序绑定的是不同的网卡,但收数据用的是一个端口,正常情况下我们可能认为端口复用只是为了解决程序运行时,这个端口还没有释放的情况,但当两个程序同时使用一个端口时,两个程序居然能同时收到数据。后续经过查阅资料,在官方文档上发现了这么一段话:
More than one process can bind to the same SOCK_DGRAM UDP port if the bind(3SOCKET) is preceded by:
int one = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))
In this case, every incoming multicast or broadcast UDP datagram destined to the shared port is delivered to all sockets bound to the port.
也就是说,如果设置了端口复用,那么无论是否绑定网卡,所有套接字都能从这个共享端口中收到数据。
根据这段话,我们再倒推,在网络协议中,网卡是在网络层进行工作的,网卡未工作,而绑定该网卡的程序却能通过端口收到数据,那么端口复用就是在网络层之上发挥作用的,即端口复用是在应用层进行工作的,也就是说,数据经过网卡传送到应用层之后,应用层通过端口复用,传递给了使用这个端口的所有套接字
网络协议可真是太复杂了...