一种命令行版的网络调试助手
背景
网络调试助手是一个用来收发网络协议包的工具,它长这样子
该工具只能运行在Windows图形界面下,虽然也有linux版,但也是运行在图形界面的,对于这群用户来说,仍然不方便:
- 调试机没有图形界面
- 调试机有图形界面,但与目标板没有网络连接,或只有串口连接
针对上面两种情况,我打算开发一个命令行版的网络调试助手。
失败的尝试
一开始打算用netcat加命名管道
加printf命令
实现,但是因为自己对命名管道
不太熟悉,摸索一番没有搞定,后来看到国外这篇论坛帖子感觉靠谱,但目测使用体验跟GUI版的网络调试助手有差距,于是决定写代码实现。
实现思路
网络连接
使用geeksforgeeks这篇文章的client.c做网络连接模板,但ip和端口号弄成可配的:
servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = inet_addr(argv[1]);servaddr.sin_port = htons(atoi(argv[2]));
协议数据转换
通过C语言的格式化输入函数sscanf
实现字符版HEX数据
到二进制数据
的转换
for (i = 0; i < count; i ++) {if (buff[i] == ' ') {i++;} else {sscanf(&buff[i], "%02hhx", &bin[j]);i += 2;j++;}}
注意,这个%hhx
就表示1字节的字符版HEX数据
,前面加个02凑成%02hhx
就能解析00
和 0A
这种加前导零的数据了。
读取服务器响应
GUI版网络调试助手会实时返回服务端的响应,但是我的命令行版不想开后台线程接收(麻烦),于是取了个巧,让用户告诉助手什么时候去读响应,这时候一定能读到响应,不会让助手卡死在read
系统调用里😉
因为这个消息是用户发给助手的,算user cmd,不是发给服务端的(算user req),因此要做区别处理,区别办法就是user cmd是以冒号开头的,参考vim
if (buff[0] == ':') {// user cmdif (strncmp(&buff[1], "read", 4) == 0) {sscanf(&buff[1+4+1], "%u", &resp_len);printf("Reading Response for %u bytes...\n", resp_len);bzero(buff, sizeof(buff));count = read(sockfd, buff, resp_len);for (i = 0; i < count; i ++) {printf("%02hhx ", buff[i]);}printf("\n");} else if ((strncmp(&buff[1], "exit", 4)) == 0) {printf("Client Exit...\n");break;}} else {// parse user req data (执行上一段的代码)// send user req datawrite(sockfd, bin, j);j = 0; // clear user req data}
目前只实现了2个user cmd:
- read #bytes,读取指定字节数的服务端响应
- exit,退出助手界面
最终效果
开2个tmux窗口,上面的串口启动netcat来假装服务端,下面的串口启动console_net_assist来当客户端,上图的交互时序为:
- 运行
netcat -l 1234
启动服务端 - 运行
./console_net_assist 127.0.0.1 1234
启动助手(即客户端) - 用户在助手的
>
提示符侧输入二进制协议数据aa 55 55 aa 00 00 00 01
,然后按回车 - 助手会将这串HEX字符串转换成二进制数据发给服务端
- 服务端处理客户端的请求数据——输出到
stdout
(netcat默认行为) - 用户在助手的
>
提示符侧输入命令:read 4
以读取约定的4字节应答 - 用户(假扮服务器)在服务端的stdin输入
good
表示4字节的响应 - 助手立即读取4字节响应并以HEX字符串的形式打印
- 用户在在助手的
>
提示符侧输入命令:exit
,退出
总结
这是个quick and dirty的小工具,谈不上代码质量,只为了解决问题,因此只有100行左右,需要的可以去我的gitee仓库下载