记一次网络连接bug解决

bug背景

项目涉及到与硬件的交互,和硬件连接使用java中基于TCP/IP的两个长连接Socket连接同一端口,硬件仅支持两个连接的建立,一旦建立,除非重置硬件Wifi模块,否则不再接受新的连接。开发过程中指导IOS开发构建了同一套PTP/IP连接模块,结果IOS在进程被杀死后,硬件会重置Wifi等待重新连接,而Android端APP进程被杀死后,硬件没有重置Wifi,所以不能直接重新连接需要手动重启硬件。

As far as we know, 所有UNIX-LIKE的系统,在进程被杀死时都会释放资源,socket更是会先发送挥手包(FIN)及完成四次挥手,那么区别在哪里呢。

肯定不在前期指令执行上,所有指令IOS和Android都是一样的,那么只可能在资源释放的环节了。

寻找IOS端和Android端进程被杀死后Socket资源释放的区别

环境

Macbook Pro + wireshark + python
IPhone
Android + root + busybox(tcpdump)

实操

由于区别主要在于TCP断开连接的方式,抓包最好使用wireshark,通过IPhone连接电脑,执行

rvictl -s 193c851574d6e7225bd9447ae03f55c5b5195802

抓取IOS所有通过当前wifi网卡的数据包,发现进程被杀死时,一个Socket发送了FIN数据包后完成了四次挥手(client FIN->server ACK-> server FIN -> client ACK),而另一个Socket使用发送了RST给硬件。


IPhone资源释放.jpg

在Android中看看Socket是怎么断开连接的,root后装上busybox,执行

adb shell su -c  tcpdump

可以直接在终端看数据包,如果想要导入wireshark中可保存数据到文件再使用wireshark打开或直接使用管道,在此不再赘述。发现Android中进程被杀死后,两个Socket都以四次挥手方式断开了


Android默认资源释放.jpg

怀着兴奋地心情尝试调为一个用RST方式断开,一个以四次挥手断开,在Java中如果想要Socket以RST方式断开连接,需要Socket参数linger为true,于是乎在Android客户端对应的Socket建立连接后,设置linger为true

socketMain.setSoLinger(true, 0)

完成后尝试,发现没有什么卵用。苦闷。。。

在苦思无果后,在Mac上尝试用python和硬件建立连接,再杀死python进程,看看硬件什么反应,花了几分钟写好python,监听数据包,执行,杀死,发现硬件重置了Wifi模块,兴奋。。。看看数据包,发现两个Socket都以RST方式断开了连接。。。

再次在Android中调整,给两个Socket都设置linger为true,成了。

总结

此次bug解决在此叙述来很简单,但是总共耗时3天,期间尝试了无数弯路,总结一下呢,bug原因仍然不知道,Android端硬件的官方应用被杀死时,两个Socket断开也都是四次挥手的方式,但是反编译其代码发现其是使用的so库实现的,暂时只能猜测和语言抽象等级或执行环境有关。。C语言下使用FIN+FIN可行,OC下使用FIN+RST可行,python下和kotlin下使用RST+RST可行,感觉就像解释执行的代码,需要RST。。

虽然bug很奇葩,但是解决过程也重温了很多底层tcp/ip的知识,工具使用也更熟练了...有时间再做个整理吧

你可能感兴趣的:(记一次网络连接bug解决)