SOCKET编程之INADDR_ANY

44 篇文章 0 订阅
33 篇文章 0 订阅

SOCKET编程之INADDR_ANY

http://blog.sina.com.cn/s/blog_6874564c0100jrvf.html


INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上来表示不确定地址,或“所有地址”,“任意地址”。一般来说,在各个系统中均定义成为0值。

例如:MontiVistaLinux中在/usr/inlcude/netinet/in.h中定义为:

 

#define INADDR_ANY   ((in_addr_t)0x00000000)

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

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

Proto     Recv-Q     Send-Q     LocalAddress     ForeignAddress     (state)

... ...

udp4                              *.7913               *.*

udp4                              *.7911               *.*

tcp4                               *.ftp                *.*            LISTEN

... ...

... ...

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

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

答案是:不会收到重复的数据包,也不会重复发送数据。

为什么呢?因为路由的关系,从客户端来的IP包只可能到达其中一个网卡。同时在服务器进程发送的数据时,操作系统根据自身维护着的路由表,决定IP数据包应该从哪一个outbound的gateway向目标端发送。根据gateway选择的不同,也就决定了从哪一个网卡/哪个IP地址发送。

为什么不会接受到重复的数据包呢?

答:因为客户端只向你的服务器上的唯一一个IP地址发送数据了。

为什么不会重复发送数据包呢?

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

如何选择发送数据的路径呢?

答:依照路由表的要求发送。

如果路由表的记录有重复/有冲突呢,这时候如何选择路径呢?

答:路由表记录有优先级别。一般来说,Windows操作系统的路由表记录,如果是重复的话,以后来加入的记录为准,而某些操作系统,象Linux/FreeBSD是不允许加入重复的路由表记录的;如果是专用的路由器,有路由选择算法,一般来说,到达网络上的某一点的路径可以有很多条的。路由选择算法可以确定“最好的一条路径”,这条路径要么是延时最小的,要么是通讯费用最低的,要么是带宽最高的,要么是跳点最小的——究竟是如何选择,就看路由器管理员如何配置了。

对于客户端,如果绑定INADDR_ANY,情况类似。对于TCP而言,在connect()系统调用时将其绑定到一具体的IP地址。选择的依据是该地址所在子网到目的地址是可达的(reachable)。这时通过getsockname()系统调用就能得到具体使用哪一个IP地址。对于UDP而言,情况比较特殊。即使使用connect()系统调用也不会绑定到一个具体地址。这是因为对UDP使用connect()并不会真正向目标地址发送任何建立连接的数据,也不会验证到目标地址的可达性,它只是将目标地址的信息记录在内部的socket()数据结构之中,供以后使用。只有当调用sendto()/ send()时,由系统内核根据路由表决定由哪一个地址(网卡)发送UDP Packet。

P.S.

在IP层中有一个路由表:在MSDOS窗口可以运行命令:netstat -r来显示路由表。根据路由表的条目指定的网卡发送数据。ARP缓存用:arp -a来显示。通常以太网帧的目的MAC地址,是下一跳的MAC地址。

文章出处:http://hi.baidu.com/523399/blog/item/a8d7b377c411931cb051b902.html

PS: 在处理自己的IP地址和/或端口的时候,有些工作是可以自动处理的。

my_addr.sin_port =0; 

my_addr.sin_addr.s_addr =INADDR_ANY; 

通过将0赋值给my_addr.sin_port,你告诉bind()自己选择合适的端口。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ixidof/archive/2010/01/30/5271509.aspx


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值