我们在树莓派上遇到了这个奇怪的问题。
我们在套接字上运行一项服务,该套接字应该通过wifi对本地和远程客户端均有效。
问题在于,停止远程网络也会停止来自本地客户端的连接。
我们的python服务器设置了一个套接字,如下所示:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_DONTROUTE, 1)
s.settimeout(2)
s.bind(("", 8888))
while True:
try:
conn, addr = s.accept()
except socket.timeout:
print("Socket timeout on s.accept(), continuing")
continue
#do stuff
我们有一个本地节点客户端每秒钟左右运行一次这样的循环(并实际发送数据):
// every second
socket.connect("localhost", "8888" );
socket.on('connect', function() { /* do stuff */ });
socket.on('error', function(ex) { });
一切正常,直到我们切断wifi。
服务器端在s.accept上超时,我们在日志中看到错误消息。
我认为套接字肯定会在0.0.0.0上监听,但是某种程度上它不会故障转移到127.0.0.1或发生某种奇怪的路由情况。
netstat -an | grep 8888
给tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:8888 127.0.0.1:52794 TIME_WAIT
tcp 0 0 127.0.0.1:8888 127.0.0.1:52724 TIME_WAIT
tcp 0 0 127.0.0.1:8888 127.0.0.1:52740 TIME_WAIT
tcp 0 0 127.0.0.1:8888 127.0.0.1:52778 TIME_WAIT
netstart -rn
给Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.1.1 0.0.0.0 UG 304 0 0 wlan0
192.168.1.0 0.0.0.0 255.255.255.0 U 304 0 0 wlan0
我猜我们只需要一个本地主机路由?
wifi恢复时,本地连接将再次建立。所以我没有在python套接字中永久删除绑定(bind)。
/etc/nsswitch.conf
中的主机行给出hosts: files mdns4_minimal [NOTFOUND=return] dns
在测试过程中,我们监视了对localhost的ping操作,并且它继续正常运行。
我们还监视了netstat,以查看端口是否在0.0.0.0上保持监听。也许这是问题所在?
最佳答案
最简单的解决方案
看来您应该避免使用我们的注释讨论中所述的“127.0.0.1”来命名。
更详细地:
根据源代码和docs(在nodejs first tests for an ip之后),它检查您是否提供了查找功能作为连接选项,否则,它将作为默认值进行自己的"dns.lookup"调用。尽管有名称,此功能实际上是在尝试使用系统命名,但可能会有所不同,例如,它可能会尝试使用ipv6。
要进一步调试,您可以尝试使用dns.lookup做一个更直接的测试用例,然后将getent ahosts|ahostsv4|ahostsv6 localhost
的输出与您的不同系统进行比较,并在wifi断开时进行比较,以及比较其他配置(例如gai.conf)以尝试确定系统命名在此系统上是否有所不同,或是否收到稍有不同的请求。