一.问题描述
某种场景下,安装有Ubuntu22系统的设备A开机后,1-2min内设备E遥控器不能遥控设备A移动,之后恢复正常。
二.设备组网
设备A和设备C之间使用modbustcp协议进行通讯。
三.首战
3.1 查看日志
放开该端口的modbus查询帧日志打印,发现整体的帧格式,发现返回了modbus数据帧,但是返回帧是82错误码的帧,可能是由网络问题导致的。
3.2 ping查看网络通路通信状况
使用ping命令,ping从机ip,查看是否能ping通,并查看丢包率,确认通路良好,延迟低、无丢包。
3.3 mNetAssist网络调试助手
在ubuntu主机上面安装网络调试助手mNetAssist,测试查询数据正常。
3.3.1 使用方法
在ubuntu上运行mNetAssist查询从机数据:
- 协议类型选择TCP客户端;
- 服务器IP和端口为指定的modbus从机的ip地址和端口;
- 本地IP填写主机查询网口的ip,本地端口随便填写会自动分配;
- 发送设置要勾选按十六进制发送;
- 接收设置可以勾选显示日期和按十六进制显示;
设置好之后,点击服务器端口下方的连接网络,如果成功建立连接,会变为断开网络,之后在本地IP下面填入要发送的modbus数据帧,点击发送,如果成功查询到数据,上方的数据接收区会显示查询结果。
注意,1、2、3、4如果设置不正确,则可能无法建立网络连接,或者发送查询数据无反应。
3.3.2 安装方法
通过百度网盘分享的文件:网络调试助手win_linux.zip
链接:https://pan.baidu.com/s/1MjVtxmtU4hTBV8wDKPN4_g
提取码:t4nu
--来自百度网盘超级会员V8的分享
下载压缩包,解压后参考其中readme.txt中的操作。
3.4 使用wireshark抓包
Ubuntu主机安装wireshark进行抓包,可以观察到,确实在开机一段时间后才开始建立连接进行通讯。同时还注意到在开机之后一段时间内,有其他的ip在和从机建立连接,并且进入了retransmission阶段,在该ip和从机重连结束后,目标主从机开始正常连接。
3.5 首战总结分析
首战,到此为止没有什么意外发现,也是在意料之中。
当前问题为开机1-2min内手柄无法遥控机器,开机之后,电脑连接路由器wifi需要一定时间,网络调试助手和wireshark都是桌面端,连接wifi之后远程桌面操作软件更需要一定时间,现在可能需要彻底搞清楚从刚刚开机到连接成功之间的网络状态。
因为是linux主机,所以可以考虑使用开机自启动脚本实现开机之后程序自启动执行所需操作。
四.再战
4.1 modbuspoll
上面我们安装的mNetAssist网络调试助手是桌面软件,需要在界面手动修改各项参数,然后建立连接,进行查询,不能应用于开机脚本自启动中,因此,我们需要找一款可以以命令行的方式工作的modbus数据帧查询软件,我选择了modbuspoll。
- ModbusPoll使用方法
mbpoll 192.168.11.12 -p 460 -B -0 -a 1 -t 1 -r 0 -c 0x10 -v
参数功能说明:
4.2 tcpdump
因为wireshark也是图形化界面操作,想要用脚本在开机后自启动抓包,就需要一款命令行操作的抓包工具,我选择了tcpdump。
直接抓取所有接口的流量:sudo tcpdump -i any -w capture.pcap
4.3开机自启动实现方式
4.3.1方式一.应用程序级启动方式
以tcpdump自启动脚本为例:
1.首先来写一个抓取数据包的脚本tcpdump_self_start_cap.sh:
#!/bin/bash
current_time=$(date +"%Y%m%d-%H%M%S")
echo "password" | sudo -S tcpdump -i any -w capture_${current_time}.pcap
注:
password:为执行sudo命令时需要输入的密码
-S: 想要sudo命令从管道中读取echo输入的密码,必须加这个参数
2.在Activities → start application → Add → Command中输入:
gnome-terminal -x bash -c "/....../tcpdump_self_start_cap.sh"
3.最终效果
该方法实现的开机自启动脚本,linux开机启动后,远程桌面登录linux系统,就会打开一个终端,并自动执行脚本程序,但是如果开机启动后不远程连接桌面,该脚本就一直不会自启动,显然这种方式并不是真正的开机自启动,也无法达到我想要的效果。
4.3.2方式二.系统级启动方式
同样以tcpdump为例,tcpdump执行脚本还是上面的脚本tcpdump_self_start_cap.sh。
1.在/etc/systemd/system路径下添加tcpdump_capture.service脚本,脚本内容如下:
[Unit]
Description=Capture network traffic using tcpdump
After=network.target
[Service]
User=root
ExecStart=/....../tcpdump_self_start_cap.sh
Restart=always
[Install]
WantedBy=multi-user.target
2.执行如下命令
sudo systemctl enable tcpdump_capture.service
sudo systemctl start tcpdump_capture.service
3.执行效果
系统开机后,不需要连接linux主机,就会自动启动脚本执行相应操作
4.4 再战总结分析
将tcpdump抓包和modbuspoll数据帧查询脚本均加入开机自启动服务,复现问题场景,观察到,开机启动后短时间内modbuspoll就可以和从机通讯,1-2min后问题软件才开始和modbus从机通讯。
dmesg、syslog和journalctl日志也未发现网络异常,经过两次测试验证,可以确认问题程序之外的其他方面应该没有问题,因此重新回到问题程序,推测是程序的什么地方耗费了较长的时间。
五.终战
5.1 回归日志和问题程序
回看之前保存的问题情况下的日志,仔细观察后发现:
tcp初始化之后一直到tcp成功连接,中间居然隔了133s,其中主要时间都浪费在了初始化和第一次连接之间:
回看代码,发现初始化到建立连接之间并没有什么耗时的操作,大胆推测是建立连接的过程比较耗时,于是在connect函数执行前后添加日志打印:
...”...before connect...”...;
sc_ -> connect(...);
...”...after connect...”...;
复现问题场景之后,可以看到:
目前想到的解决办法是调用异步async_connect函数建立连接,结合deadline_timer增加超时时间,是否能解决当前问题尚未测试验证
5.2 终战总结分析
1.看日志还是要认真仔细一点;
2.学习别人的源码还是要细节一点;
PS:希望这篇记录能对大家在使用文中提及的工具上有所帮助,更深的帮助应该是没有了。
标签:脚本,...,蚊子,自启动,开机,大炮,modbustcp,tcpdump,连接 From: https://www.cnblogs.com/WuLaRua/p/18521583