INADDR_ANY,bind,htos(0)

news/2024/5/17 17:27:34 标签: 服务器, socket, internet, 网络, 路由器, tcp
INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。 一般来说,在各个系统中均定义成为0值。

例如MontiVista Linux中在/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.
P.S.
-----------------------------------------------------------------------------
在IP层中有一个路由表:
在MSDOS窗口可以运行命令:netstat -r
来显示路由表。根据路由表的条目从指定的网卡发送数据。
ARP缓存用:arp -a
来显示。
通常以太网帧的目的MAC地址,是下一跳的MAC地址。 

在IP层中有一个路由表:
在MSDOS窗口可以运行命令:netstat -r
来显示路由表。根据路由表的条目从指定的网卡发送数据。
ARP缓存用:arp -a

htos(0)
1024-5000
在Internet地址族中,一个名字包括几个组成部分,对于SOCK_PGRAM和SOCK_STREAM类套接口,名字由三部分组成:主机地址,协议号(显式设置为UDP和TCP)和用以区分应用的端口号。如果一个应用并不关心分配给它的地址,则可将Internet地址设置为INADDR_ANY,或将端口号置为0。如果Internet地址段为INADDR_ANY,则可使用任意网络接口;在有多种主机环境下可简化编程。如果端口号置为0,则WINDOWS套接口实现将给应用程序分配一个值在1024到5000之间的唯一的端口。

 

 

[cpp]  view plain copy
  1.    struct sockaddr_in  from = {0};  
  2.    //本地地址  
  3.    from.sin_addr.s_addr     = INADDR_ANY;//NADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,  
  4.    //或“所有地址”、“任意地址”。 一般来说,在各个系统中均定义成为0值。  
  5.    from.sin_family          = AF_INET;  
  6.    from.sin_port            = htons(SocketStatus[dwIndex].lPort); //本地端口=0  
  7.    //在1024~5000之间自动分配一个没有使用的端口!  
  8. /SO_LINGER 确保数据安全且可靠的传送出去。本程序设置为0;  
  9.    struct linger ling = {0};     
  10.    //数据没有发送完成时,允许逗留0s  
  11.    if(setsockopt(skt, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) == SOCKET_ERROR)//ling逗留时间SOCKET_ERROR==-1  
  12.      
  13.    /* 可以绑扎到一个已经使用的本地地址,允许本地地址复用 */  
  14. //(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket  
  15.    if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void *)&intOptVal, sizeof(intOptVal)) == SOCKET_ERROR)  
  16.   
  17.   
  18.    bind()  
  19.    listen()  
  20.      
  21.     flags = fcntl(skt, F_GETFL);//获取文件描述符标志  
  22.    if (fcntl(skt, F_SETFL, flags | O_NDELAY) == SOCKET_ERROR)//设置非阻塞模式  
  23.    //以不可阻断的方式打开文件,也就是无论有无数据读取或等待,都会立即返回进程之中  
  24.    //=O_NONBLOCK O_NDELAY  
  25. //Non-blocking I/O.   
  26.   
  27. //O_NONBLOCK  
  28. //POSIX-style non-blocking I/O.   



http://www.niftyadmin.cn/n/849806.html

相关文章

享元(Flyweight)模式

2019独角兽企业重金招聘Python工程师标准>>> package JAVABasic;import java.util.ArrayList; import java.util.Collection; /*** 享元模式的核心思想就是将内部状态相同的对象在存储时进行缓存。* 也就是说同一颜色同一尺寸的皮鞋,我们在内存中只保留一…

1057 传球

1057 传球 国庆最后一道题,做完赶紧肝作业 其实这一个题就比较简单了,因为我学会了套用五部曲了,真棒! 感觉这个题算是dp中比较基础的了,首先,我们先弄明白这个题中,我们需要维哪些信息&#x…

android tomcat乱码问题,Android访问服务器(TOMCAT)乱码引发的问题

1、浏览器往服务器发送的请求主要可分为2种:get、post;delete、head等不赘述。GET方式:从浏览器上直接敲地址,最大特点就是参数直接跟在地址后面。POST方式:表单提交等。2、访问过程:浏览器中输入地址 –&g…

exec ---shell

exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息。bash shell的命令分为两类:外部命令和内部命令。外部命令是通过系统调用或独立的程序实现的,如sed…

成功的心态

2019独角兽企业重金招聘Python工程师标准>>> 雨后,一只蜘蛛艰难地向墙上已经支离破碎的网爬去,由于墙壁潮湿,它爬到一定的高度,就会掉下来,它一次次地向上爬,一次次地又掉下来...... 第一个人看…

sockaddr与sockaddr_in结构体简介

sockaddr与sockaddr_in结构体简介2007-09-01 20:56【标 题】:sockaddr与sockaddr_in结构体简介 【关键字】:sockaddr,sockaddr_in 【来 源】:ttp://blog.csdn.net/lihengzk/archive/2006/11/26/1415312.aspx sockaddr与sockaddr_in结构体…

ERROR:In..\..\Source\IO\vtkDataReader.cxx,line462

根据《三维图像编程实验》p52的例程去操作,打开.vtk文件时提示如下错误。 图1 根据图1第2行的提示:vtkDataSetReader[04A184B0]:Unable to open file:hello.vtk,可以知道问题是“无法打开hello.vtk”。通常情况下,打开文件都是以路…

List容器三种排序示例

2019独角兽企业重金招聘Python工程师标准>>> import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List;/*** *//*** 类说明: List排序三种示例* Time: 2014-1-21 下午3:25:17 * author 凯文加内特* Company…