单网卡多IP导致的socket connect 10060超时错误
问题:
接管别人代码时遗留的一个bug,在win7下,给一个网卡设置多个ip时,发现无法连接上服务器了。XP下就不会,这多个ip为192.168.1.127,172.1.1.13,10.0.0.1。
复现过程:
复现的过程中我的服务器ip为192.168.1.128,子网掩码255.255.255.0,默认网关为192.168.1.128(服务器不需要联网,所以就这么设置了)。
客户端按照bug说明设置了对应的3个IP。
发现无法复现,然后和测试沟通要求重现,发现他那边设置这样的IP是会出现的。因此比较了下他的服务器IP和我的服务器IP的区别,竟然是默认网关的问题,设置成192.168.1.1就能复现了。(后来发现设置成其他的也可以)。
解决过程:
首先恶补了一下IP、子网掩码、网关的知识。(都还给老师了)(socket技术也不是很熟悉)
分析的话还是从客户端IP开始,首先3个IP中肯定要存在的是192.168.1.127,因为只有这个IP和服务器同网段,其他两个都是不同网段的,并且刚好占据了A、B、C三类IP。于是试着去掉172网段的IP,发现也会复现。
OK,那基本确定就是因为存在一个不同网段的IP导致连接不上服务器了,于是去看源代码,跟踪发现是在调用getaddrinfo时,传入本主机名称,返回的IP列表中存在两个IP,但是代码里面默认就只使用第一个,这win7下第一个刚好是10.0.0.1,当然就无法和192.168.1.128的服务器通信了。测试了下XP下刚好第一个IP是和服务器同网段的,所以就能通信。(不过这里有个疑问就是服务器默认网关设置成192.168.1.128时仍然能通信,这是为什么?)
因为后面调用connect的地方和getaddrinfo的地方不在同一个层级,而且都已经经过了封装,想要将返回的IP列表全部返回到connect的地方会牵涉到比较大的改动,我比较担心引发新的BUG。所以决定在返回Ip给connect使用之前就过滤出和服务器IP在同一网段的IP。
这里是将服务器IP传进去作为一个参照对象。将返回的IP列表中的IP全部转换成unsigned long类型,然后和服务器IP做差,差值最小的就是最接近服务器IP的(认为是和服务器IP同网段的)。要注意的是,inet_addr函数返回的unsigned long是将高段的值放置在末尾的,所以这里调用了ntohl函数将unsigned long逆序一遍。
代码片段如下:
if ( SOCKET_ERROR != getaddrinfo(pstrHost, pstrService, &aiHints, &aiList) && ( aiList != 0 ))
{
// 优先匹配在同一网段的IP地址来使用
ADDRINFO *aiUse = aiList;
if(NULL != aiUse->ai_next && NULL != pszRemote && AF_INET == nFamily) // 只支持ip4的
{
char szAddress[MAX_PATH] = { 0 };
ADDRINFO* aiCrt = aiUse;
unsigned long lulMinimumDiff = 0xffffffff;
unsigned long llRemote = ntohl(inet_addr(pszRemote));
unsigned long llCrt = 0;
unsigned long llDiff = 0;
while(NULL != aiCrt)
{
// 转换成数值,差值最小的就是ip最接近的
const void* addr = &((const sockaddr_in*)aiCrt->ai_addr)->sin_addr;
if (inet_ntop(nFamily, addr, szAddress, MAX_PATH) != NULL)
{
llCrt = ntohl(inet_addr(szAddress));
if(llCrt > llRemote)
llDiff = llCrt - llRemote;
else
llDiff = llRemote - llCrt; if(llDiff < lulMinimumDiff)
{
lulMinimumDiff = llDiff;
aiUse = aiCrt;
}
} aiCrt = aiCrt->ai_next;
}
}
ADDRINFO ai = { 0 };
ai.ai_addr = sockAddr;
memcpy(ai.ai_addr, aiUse->ai_addr, aiUse->ai_addrlen);
freeaddrinfo( aiList );
return true;}
单网卡多IP导致的socket connect 10060超时错误的更多相关文章
- Linux 单网卡多 IP 的配置方法
Linux 单网卡多 IP 的配置方法 1 .永久配置的方法: 知道在 Linux 下网卡被称为 eth0,eth1,eth2..... ,所有网卡的配置文件都存储在 /etc/sysconfi ...
- linux单网卡多IP配置
一.仅一个网卡的情况下,可以让该机器可以通过多个IP被访问,或隐藏常用IP,让他人访问其临时IP. 1.如果临时性的增加一个IP(重启机器或network服务后,丢失),可以使用ifconfig命令 ...
- 如何在centos上配置802.1Q VLAN标记,linux单网卡多vlan多网段Ip配置案例
介绍 VLAN使将大型网络分成较小且易于管理的网络成为可能.802.1Q是所有供应商都在其网络设备中实施的标准.某些交换机能够将多个VLAN分配给单个网络端口.使用此功能,您可以将多个VLAN分配给单 ...
- centos linux系统日常管理复习 CPU物理数逻辑核数,iftop ,iotop ,sar ,ps,netstat ,一网卡多IP,mii-tool 连接,ethtool速率,一个网卡配置多个IP,mii-tool 连接,ethtool速率 ,crontab备份, 第十八节课
centos linux系统日常管理复习 物理CPU和每颗CPU的逻辑核数,uptime ,w,vmstat,iftop ,iotop ,sar ,ps,netstat ,一个网卡配置多个IP,mii ...
- Linux多网卡多IP配置
echo "210 local100" >> /etc/iproute2/rt_tables echo "220 local200" >> ...
- Ubuntu下单网卡多IP地址的配置
删除用户默认配置文件 由于在默认清空下,配置文件是系统自动生成的用户设备配置文件保存在/etc/udev/rule.d/下面:# cp /etc/udev/rule.d /etc/udev/rule. ...
- LINUX一网卡多IP设置
方法1:少量IP手动绑定(这里以绑定IP到eth0为例,其它网卡的话修改相应的文件名即可) 1.复制ifcfg-eth0的网卡配置文件并改名为ifcfg-eth0:0 [root@akinlau /] ...
- 配置多网卡多IP的方式
[root@web01 conf.d]# cat ip.conf server { listen 10.0.0.7:80; server_name _; location ...
- 一块网卡多个IP实现
////////////////////////////写在前面//////////////////////////////////////////// 需要注意,这里我们是一块网卡多个IP,而并非是 ...
随机推荐
- 【高级算法】模拟退火算法解决3SAT问题(C++实现)
转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46453761 ---------------------------------- ...
- java JMS消息队列
http://blog.csdn.net/shirdrn/article/details/6362792 http://haohaoxuexi.iteye.com/blog/1893038 http: ...
- 再次记录老K站点的工作策略
股市开盘了. 据说今天是多空决战的日子. 7月17日.三大期指交割. 打开大盘,看着指数一会上升,一会跳水.好不欢乐.当然,今天我是来记录我的老K,关于老K的下一步. 近期每天傍晚的时候.都会去江边散 ...
- redis 控制调用频率
redis提供了rate limit demo 如下所示: INCR key Available since 1.0.0. Time complexity: O(1) Increments the n ...
- Java基础知识强化之集合框架笔记02:集合的继承体系图解
1. 集合的继承体系图解:
- 在Github上面搭建Hexo博客(一):部署到Github
什么是Hexo Hexo是一个基于Node.js的静态博客程序,可以方便的生成静态网页托管在Github和Heroku上.并且有很多人为其制作了很多优秀的主题(theme),你可以根据自己的喜好进行设 ...
- hdu 2689
hdu 2689 超级大水题....两种代码都过了,开始以为n^2会tle,后来竟然过了...汗 注意下cin写在while里面,就可以了 #include <iostream> usin ...
- YII框架中php入口文件隐藏
Apache配置修改 主要修改下httpd文件中的两个地方 1.启用mod_rewrite.so模块,在Apache的配置文件中找到如下行,去掉前面的字符"#",保存 #LoadM ...
- C# - 使用 OLEDB读取 excel(不用Excel对象).
参考: How to read from an Excel file using OLEDB 为了使用方便,我做成了工具类(OledbCommon.cs),好以后使用. 注:连接字符串中,Provid ...
- 打开的IE网页不是最大化的解决方法
方法一:先把所有的IE窗口关了;只打开一个IE窗口;最大化这个窗口;关了它;OK,以后的默认都是最大化的了 方法二:先关闭所有的IE浏览器窗口,用鼠标右键点击快速启动栏的IE浏览器图标,在出现的快捷菜 ...