关于socket绑定INADDR_ANY

Posted loanhicks

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于socket绑定INADDR_ANY相关的知识,希望对你有一定的参考价值。

其中INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。

一般情况下,如果你要建立网络服务器,则你要通知服务器操作系统:请在某地址 xxx.xxx.xxx.xxx上的某端口 yyyy上进行侦听,并且把侦听到的数据包发送给我。这个过程,你是通过bind()系统调用完成的。——也就是说,你的程序要绑定服务器的某地址,或者说:把服务器的某地址上的某端口占为已用。服务器操作系统可以给你这个指定的地址,也可以不给你。

如果你的服务器有多个网卡,
而你的服务(不管是在udp端口上侦听,还是在tcp端口上侦听),出于某种原因:可能是你的服务器操作系统可能随时增减IP地址,也有可能是为了省去确定服务器上有什么网络端口(网卡)的麻烦 —— 可以要在调用bind()的时候,告诉操作系统:“我需要在 yyyy 端口上侦听,所以发送到服务器的这个端口,不管是哪个网卡/哪个IP地址接收到的数据,都是我处理的。”这时候,服务器则在0.0.0.0这个地址上进行侦听。例如:

Proto Recv-Q Send-Q Local Address Foreign Address (state)
……
udp4 0 0 *.7913 *.* 
udp4 0 0 *.7911 *.*
tcp4 0 0 *.ftp *.* LISTEN
……
……

以上这些是网络侦听的情况,其中Local Address 为 “*.ftp”、“*.7911”等,代表了服务程序绑定了服务器的所有网卡。

 

 

具体一点:

 

 

 

比如你的机器有三个ip   
  192.168.1.1   
  202.202.202.202   
  61.1.2.3   
    
  如果你serv.sin_addr.s_addr=inet_addr("192.168.1.1");   
    
  然后监听100端口   
    
  这时其他机器只有connect   192.168.1.1:100才能成功。   
  connect   202.202.202.202:100和connect   61.1.2.3:100都会失败。   
    
  如果serv.sin_addr.s_addr=htonl(INADDR_ANY);   的话,无论连接哪个ip都可以连上的。

 

 

好了,你明白了侦听INADDR_ANY是什么意思了,那么,我的服务器有N个IP地址,会不会收到重复的数据包?收到数据包后,是不是会重复回复客户端呢?
答案是:不会收到重复的数据包,也不会重复发送数据。

为什么呢?楼上说得对,每一个服务器都有维护着一个路由表。数据包应该向哪里发送,是由路由表决定的。

为什么不会接收到重复的数据包呢?
答:因为客户端只向你的服务器上的唯一一个IP地址发送数据了。

为什么不会重复发送数据包呢?
答:因为发送数据包的路由(路径)是唯一的。如果服务器不知道在发送数据的时候应该向哪个地址发送数据,那么数据就会被发送到“默认网关”上。

如何选择发送数据的路径呢?
答:依照路由表的要求发送。

如果路由表的记录有重复/有冲突呢,这时候如何选择路径呢?
答:路由表记录有优先级别。一般来说,Windows操作系统的路由表记录,如果是重复的话,以后来加入的记录为准,而某些操作系统,象linux/FreeBSD是不允许加入重复的路由表记录的。

以上是关于关于socket绑定INADDR_ANY的主要内容,如果未能解决你的问题,请参考以下文章

找出异步套接字绑定的端口?

Python:绑定套接字:“地址已在使用中”

socket编程:bind函数是把socket绑定到具体窗口?

为啥 socket.gethostbyname(socket.gethostname) 只绑定到本地 IP 地址?

zeromq怎样获取已经绑定的socket节点

socket_bind() 无法绑定地址