缘起:
最近一个项目要上线,我负责的应用需要和设备进行通信,按照之前约定的协议,大家使用的是tcp/ip 的通信方式。设备侧作为server,而我们作为的是client,其中心跳维护是由client侧主动发起。
在入场联调的时候,双方在一个命令回复的报文里面产生了分歧。我们认为没有收到设备侧的回复,但是设备厂家说我已经回复了,几番争论之后,我们开始抓包分析(之前都是通过我们应用的日志信息确认问题)。在Linux服务上进行网络抓包,最常见的就是使用tcpdump,它功能很强大,他提供了很多参数以及正则表达式来对抓包的数据进行过滤。而我们这里就是简单粗暴的对eth0这个网卡上的所有通信信息进行抓包。当通过tcpdump把包抓下来之后,然后通过scp到本机,然后通过wireshark在本机分析抓包结果,最后确认与设备侧的通信问题。
具体的tcpdump的命令介绍,可以参考这篇文章:戳这里
解决:
我们这里用到的命令就是:
tcpdump -s 0 -w /tmp/aa
就是获取所有通信包信息,并将信息写入到/tmp下的aa文件中。在本机用wireshark打开这个aa文件,过滤出属于2000端口的信息,截图如下:
最后通过抓包分析确认是设备厂商的问题,最后问题解决。
扩展:
因为项目近期上线,通信上的问题有可能随时发生,因此需要把tcpdump一直开着,这样方便出现问题后快速定位问题。而Tcpdump写文件的方式是一直在同一个文件上进行追加,如果一定时间后,这个文件就会变得非常大,这样不利于后面的分析。因此,我们需要对dump出来的文件,做一个切割。
第一次我们想到的是通过cronolog这个屌炸天的东东来进行分割,在网上搜索对应的应用你发现先很多人将其应用到Nginx或者Apache的日志处理上。经过一番尝试发现这哥们无法与tcpdump进行合并使用(也许是没有找到使用方法),无赖放弃转战另一条路。
第二次我们想到使用一个死循环的脚本,通过tcpdump的-c参数,将按照每多少个通信包一个文件的方式进行生成,最后脚本完成试验效果不错,几乎是每隔50M左右一个文件。如下截图:
脚本如下:
#!/bin/sh
n=0
while true ; do
n=$(( $n + 1 ))
tcpdump -s 0 -c 102400 -w /tmp/tcpdump/tcpdump.out.$n
done
最后:
通过这个case,我想厂商或者联调的另一方不相信你的程序日志是可以理解的,但是你可以通过公认的工具,找到事实,他就必须得相信了,所以我们要有这种快速找到问题的能力。