Socket INADDR_ANY详解
转载:http://hi.baidu.com/zorro_knight/item/37af9e8c9dc71253e73d1924
linux下的socket INADDR_ANY表示的是一个服务器上所有的网卡(服务器可能不止一个网卡)
多个本地ip地址都进行绑定端口号,进行侦听。
不光是多个网卡的问题.
见如下server listen:
80           0.0.0.0               //INADDR_ANY,外部的client ask 从哪个server的地址近来都可以连接到80端口.
8088       192.168.1.11     //外部的client ask 从server地址192.168.1.11进来才可以连接到8088端口.
8089       192.168.1.12     //外部的client ask 从server地址192.168.1.12进来才可以连接到8089端口.
也就是说0.0.0.0 是指本地的地址(也就是代表了所有本地的地址,同一个网卡上也可能有多个地址).
这点上linux,windows系统都是相同的.
而对于在connect中指定了INADDR_ANY,那么: 
  1. 在语义上一定是连接到本地地址,不可能是外部地址.
  2. INADDR_ANY在语义上有可能是对应了几个本地地址,因此有的系统会根据缺省规则连接本地指定的服务,而有的系统则因为不能确定用户的任意本地地址是哪个而不能有效连接(如linux和windows不同).
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 的具体含义是,绑定到0.0.0.0。此时,对所有的地址都将是有效的,如果系统考虑冗余,采用多个网卡的话,那么使用此种bind,将在所有网卡上进行绑定。在这种情况下,你可以收到发送到所有有效地址上数据包。
例如:
SOCKADDR_IN Local;
Local.sin_addr.s_addr = htonl(INADDR_ANY);
  
  另外一种方式如下:
SOCKADDR_IN Local;
hostent* thisHost = gethostbyname("");
char* ip = inet_ntoa(*(struct in_addr *)*thisHost->h_addr_list);
Local.sin_addr.s_addr = inet_addr(ip);
在这种方式下,将在系统中当前第一个可用地址上进行绑定。在多网卡的环境下,可能会出问题。
  
  最常见的方式:
const char LocalIP[] = "192.168.0.100";
SOCKADDR_IN Local;
Local.sin_addr.s_addr = inet_addr(LocalIP);
bind(socket, (LPSOCKADDR)&Local, sizeof(SOCKADDR_IN)
  bind的安全问题:
  如果你在bind时,使用了INADDR_ANY那么,你将可以在所有有效的地址上进行监听,但是Socket有一个特性:可在同一端口上绑定多个Socket。
让我们看看下面的情况:假设你的系统只有一个IP:192.168.0.100,你希望bind到4096端口。对于下面的两种bind,当数据包到达时,谁会接收到呢?
Local.sin_addr.s_addr = htonl(INADDR_ANY);
Local.sin_addr.s_addr = inet_addr(“192.168.0.100”);
 
 WinSocke库是这样处理的:谁绑定的最明确,谁获取数据包。显然,第二种bind将获取到达的数据包。如果避免这种情况呢?使用
SO_EXECLUSINEADDRUSE选项。需要注意的是,此选项在Windows NT 4 Service Pack
4以后(包括SP4)才可以使用。
示例代码:
#ifndef SO_EXECLUSINEADDRUSE
#define SO_EXECLUSINEADDRUSE ((int)(~SO_REUSEADDR))
  #endif
  
SOCKADDR_IN Local;
BOOL val = TRUE;
  
  Local. sin_family = AF_INET;
Local. sin_port = htons(4096);
Local.sin_addr.s_addr = htonl(INADDR_ANY);
  
  setsocketopt(socket,
SOL_SOCKET,
SO_EXECLUSINEADDRUSE,
(char*)&val,
sizeof(val));
  
  bind(socket, (LPSOCKADDR)&Local, sizeof(SOCKADDR_IN)
对
于客户端如果绑定INADDR_ANY,情况类似。对于TCP而言,在connect()系统调用时将其绑顶到一具体的IP地址。选择的依据是该地址所在
子网到目标地址是可达的(reachable). 这时通过getsockname()系统调用就能得知具体使用哪一个地址。对于UDP而言,
情况比较特殊。即使使用connect()系统调用也不会绑定到一具体地址。这是因为对UDP使用connect()并不会真正向目标地址发送任何建立连
接的数据,也不会验证到目标地址的可达性。它只是将目标地址的信息记录在内部的socket数据结构之中,共以后使用。只有当调用
sendto()/send()时,由系统内核根据路由表决定由哪一个地址(网卡)发送UDP packet.
SOCKET bind INADDR_LOOPBACK和INADDR_ANY的区别
今天写程序时候,服务器端启动了,然后客户端总是连接不上,connect返回错误号是10061,服务器积极拒绝请求。
用telnet连接一下端口,发现服务端服务没有开启,但是我程序是启动的,用netstat -a 命令看服务器是监听状态。
把流程走一遍,发现bind用的参数是INADDR_LOOPBACK,改成INADDR_ANY就OK了。
只是有些困惑,因为之前一个程序用的是INADDR_LOOPBACK运行没有问题,为何这里运行不了?
sa.sin_addr.s_addr        = htonl(INADDR_LOOPBACK); // 1
sa.sin_addr.s_addr        = htonl(INADDR_ANY  ); //2
两者的区别
INADDR_ANY是ANY,是绑定地址0.0.0.0上的监听, 能收到任意一块网卡的连接;
INADDR_LOOPBACK, 也就是绑定地址LOOPBAC, 往往是127.0.0.1, 只能收到127.0.0.1上面的连接请求
Socket INADDR_ANY详解的更多相关文章
- windows socket函数详解
		windows socket函数详解 近期一直用第三方库写网络编程,反倒是遗忘了网络编程最底层的知识.因而产生了整理Winsock函数库的想法.以下知识点均来源于MSDN,本人只做翻译工作.虽然很多前 ... 
- socket接口详解
		1. socket概述 socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信. socket起源于UNIX,在Unix一切 ... 
- Linux的SOCKET编程详解(转)
		Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ... 
- 【ARM-Linux开发】Linux的SOCKET编程详解
		Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ... 
- Socket 死连接详解
		Socket 死连接详解 当使用 Socket 进行通信时,由于各种不同的因素,都有可能导致死连接停留在服务器端,假如服务端需要处理的连接较多,就有可能造成服务器资源严重浪费,对此,本文将阐述其原理以 ... 
- socket原理详解
		1.什么是socket 我们知道进程通信的方法有管道.命名管道.信号.消息队列.共享内存.信号量,这些方法都要求通信的两个进程位于同一个主机.但是如果通信双方不在同一个主机又该如何进行通信呢?在计算机 ... 
- Android Socket通信详解
		一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客 ... 
- c/c++ socket函数详解
		c/c++ socket函数详解 注意: 使用socketAPI前,要先将相关链接库(Ws2_32.lib)加入链接,并使用WSAStartUp函数初始化.每个socket函数都可能失败(返回-1), ... 
- (转)python标准库中socket模块详解
		python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ... 
随机推荐
- POJ 3159 Candies(差分约束+spfa+链式前向星)
			题目链接:http://poj.org/problem?id=3159 题目大意:给n个人派糖果,给出m组数据,每组数据包含A,B,C三个数,意思是A的糖果数比B少的个数不多于C,即B的糖果数 - A ... 
- 机器学习-sklearn-learn
			随即森林 from sklearn import neighbors, datasets, preprocessing from sklearn.model_selection import trai ... 
- CentOS6.9下安装MariaDB10.2.11
			yum groupinstall -y "Development Tools" yum install -y cmake openssl-devel zlib-devel yum ... 
- 在Windows中安装Boot2Docker 遇到 Unable to load R3 module 的解决方案
			引言 这个几乎是所有64位win7用户在virtual box上安装64位的linux都会遇到的问题(如果你用的是买机器的时候自带的win7 64位而且你没有重装过系统的除外). 解决办法 可参考以下 ... 
- IE8/9的几个前端bug解决方案
			最近做的东西需要兼容IE……啊真是令人忧伤…… 解决低版本IE的buggy inline-block 低版本的IE只对本身inline的元素能用inline-block,而本身为block的元素需要设 ... 
- Java学习(构造方法、this关键字、super应用)
			构 造 方 法 定义:对象创建时使用的方法,即在new一个新对象时,对应构造方法,直接对属性赋值. 语句格式: 修饰符(public 等) 构造方法名(必须跟当前类名一样,否则报错)(参数列表) ... 
- loadrunner 学习笔记--AJAX
			用loadrunner测试WEB程序的时候总是会碰到AJAX或者ActiveX实现的功能,而通常这些功能会包含很多客户端函数(一般为JavaScript).我们该如何处理?如果从功能实现的角度去考虑这 ... 
- asp.net传多个值到其它页面的方法
			网站开发中,在页面之间的跳转,经常会用到传值,其中可能会传递多个值. 一.CommadArgument传多个值到其他页面. 像Gridview dataList repeater等数据绑定控件中,可以 ... 
- cogs——2478. [HZOI 2016]简单的最近公共祖先
			2478. [HZOI 2016]简单的最近公共祖先 ★☆ 输入文件:easy_LCA.in 输出文件:easy_LCA.out 简单对比时间限制:2 s 内存限制:128 MB [题 ... 
- iOS 9音频应用播放音频之播放控制暂停停止前进后退的设置
			iOS 9音频应用播放音频之播放控制暂停停止前进后退的设置 ios9音频应用播放控制 在“iOS 9音频应用播放音频之ios9音频基本功能”一文可以看到AVAudioPlayer类有很多的属性以及方法 ... 
