个人问题发生环境:
1.TCP服务器是虚拟机,IP地址是192.168.8.12。
2.TCP客户端是宿主机,IP地址是192.168.8.11。
3.从宿主机(192.168.8.11)上启动Socket,发现无响应。
4.从服务器(192.168.8.12)上抓包,发现能抓到来自宿主机(192.168.8.11)的SYN消息。
5.然而服务器不响应SYN,ACK。
排查过程:
一、去网上找了找,可能的原因之一就是时间戳的问题。
当客户端发出的syn包带有时间戳的情况下,经过NAT转换后,如果使用的端口被之前使用过,而且时间戳大于本次syn包中的时间戳。系统将会直接丢弃。造成本次链接无法正常完成TCP/IP的3次握手。
解决的方法很简单,分为两种:
在客户端:关闭rfc1323
在服务端:设置sysctl.conf里面tcp_timestamps=0也可以只用命令sysctl -w net.ipv4.tcp_timestamps=0
尝试了一下,在我的环境里解决不了问题。
二、找不到其他的原因了,由于之前我的客户端是能够成功连接服务器的。
我用了一个最直接的方法,重新写了一个只连接的简单的TCP客户端链接例子。
奇怪的事情发生了,这个DEMO能链接成功!
三、步骤二是个好消息,我可以抓包对比了。
失望:所有的TCP设置参数都是一样的。
继续分析包的上层内容。
转机:网络层的MAC地址不一样!
四、问题初步原因找到了。
虚拟机不回复SYN的原因是这个时候的包的目的地不是虚拟机,虚拟机起了个中转作用。
目的地是哪儿呢?我扫描局域网内的机器,发现是我的网关地址。
五、进一步的原因?
为什么看起来同样的代码,却导向了不同的网络目的地,涉及网关,那就是跨网段路由了啊?
六、真相只有一个!
手动写的Demo,服务器的地址是静态的字符串“192.168.8.12”。
出问题的程序,我从配置文件里读取的配置信息,而配置的地址是“192.168.1.12”(两个开发环境的内网网段不一样)。
简单的总结原因就是【粗心】。