免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1201 | 回复: 0
打印 上一主题 下一主题

[socket]Socket INADDR_ANY详解 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-12-08 15:08 |只看该作者 |倒序浏览

[color="#000066"]Socket INADDR_ANY详解
INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。
一般来说,在各个系统中均定义成为0值。
例如在ubuntu的/usr/include/netinet/in.h定义为:
/* Address to accept any incoming messages.  */
#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  Local Address          Foreign Address        
(state)
……
udp4       0      0  *.7913                 
*.*                    
udp4       0      0  *.7911                 
*.*
tcp4       0      0  *.ftp                  *.*                    
LISTEN
……
……
以上这些是网络侦听的情况,其中Local Address 为
“*.ftp”、“*.7911”等,代表了服务程序绑定了服务器的所有网卡。
好了,你明白了侦听INADDR_ANY是什么意思了,那么,我的服务器有N个IP地址,会不会收到重复的数据包?收到数据包后,是不是会重复回复客户端呢?
答案是:不会收到重复的数据包,也不会重复发送数据。
为什么呢?因为路由的关系,从客户端来的IP包只可能到达其中一个网卡。同时在服务器进程发送数据时,操作系统根据自身维护着的路由表,决定IP数据包应该
c从哪一个outbound的gateway向目标端发送。根据gateway选择的不同,也就决定了从哪一个网卡/哪个IP地址发送。
为什么不会接收到重复的数据包呢?
答:因为客户端只向你的服务器上的唯一一个IP地址发送数据了。
为什么不会重复发送数据包呢?
答:因为发送数据包的路由(路径)是唯一的。如果服务器不知道在发送数据的时候应该向哪个地址发送数据,那么数据就会被发送到“默认网关”上。
如何选择发送数据的路径呢?
答:依照路由表的要求发送。
如果路由表的记录有重复/有冲突呢,这时候如何选择路径呢?
答:路由表记录有优先级别。一般来说,Windows操作系统的路由表记录,如果是重复的话,以后来加入的记录为准,而某些操作系统,象linux/FreeBSD是不允许加入重复的路由表记录的;
如果是专用的路由器,有路由选择算法,一般来说,到达网络上的某一点的路径是可以有很多条的。路由选择算法可以确定“最好的一条路径”,这条路径要么是延时最小的,要么是通讯费用最低的,要么是带宽最高的,要么是跳点最小的——究竟是如何选择,就看路由器的管理员如何配置了。
对于客户端如果绑定INADDR_ANY,情况类似。对于TCP而言,在connect()系统调用时将其绑顶到一具体的IP地址。选择的依据是该地址所在子网到目标地址是可达的(reachable).
这时通过getsockname()系统调用就能得知具体使用哪一个地址。对于UDP而言,
情况比较特殊。即使使用connect()系统调用也不会绑定到一具体地址。这是因为对UDP使用connect()并不会真正向目标地址发送任何建立连接的数据,也不会验证到目标地址的可达性。它只是将目标地址的信息记录在内部的socket数据结构之中,共以后使用。只有当调用
sendto()/send()时,由系统内核根据路由表决定由哪一个地址(网卡)发送UDP packet.
               
               
               
int tc_server_socket(int port )
    {
        int sockfd = socket(PF_INET, SOCK_STREAM, 0);
        struct sockaddr_in my_addr;
        memset(&my_addr, 0, sizeof(my_addr));
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(port);
        my_addr.sin_addr.s_addr =htonl( INADDR_ANY );
        bzero(&(my_addr.sin_zero),8);
        
        if(sockfd>0)
        {
            int on = 1;
            setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
            if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1)
            {
                sockfd = -2;
                TCMD_TRACE("bind error!!");               
            }
            else
            {
                   if(listen(sockfd,10)== -1)            
                   {
                  sockfd = -3;
                  TCMD_TRACE("listen error!!");                                                                     
                   }
                   else
                   {
                     TCMD_TRACE("listen no error!!");
                   }                        
            }
        }
        return sockfd;
    }


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/63775/showart_1685893.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP