问题背景
公司有一套消息推送系统(简称GCM),由于人事变动接手了其中的客户端部分。看了一下文档,仅通讯协议部分有几页简单的说明,代码呢又多又乱,一时理不出一个头绪。由于消息是从后台推送到端的,所以使用了 tcp 长连接通道来保证消息的及时性,基于 http 的一堆分析工具(如 postman)完全没有用武之地,因此决定写个小工具来模拟 tcp 上的通讯协议,作为深入熟悉代码之前的热身。
问题的解决
一开始想用 c++ 来写这个工具,但是想到 socket 一连串经典的(socket / bind / connect / send / recv…)的繁琐调用我还是算了,之前用 shell 写过几个小工具很舒爽,但那都是借用 curl 命令来处理 http 协议,面对 tcp 协议 curl 肯定是无能为力了,因为命令执行完成后连接也就断开了,无法模拟长连接。那是不是就不能用 shell 写了呢?非也。
连接的建立与断开
我突然想到 shell 本身好像可以支持将 tcp 连接打开为文件:
bash;gutter:false;
exec N <> /dev/tcp/host/port</p>
<pre><code>
上面这段脚本就可以在句柄为 N 的文件上打开到 host 且端口为 port 的 tcp 连接了,并且可以进行双向读写。于是赶快在 msys2 中试了一下:
</code></pre>
<p>1 exec 3<>/dev/tcp/$gcm_host/$gcm_port
2 ret=$?</p>
<p>3 echo "open tcp $ret"
4 if [ $ret != 0 ]; then
5 echo "connect to gcmserver failed"
6 exit 1
7 fi
8
9 echo "connect with server"</p>
<pre><code>
这里脚本直接使用标准输入(0)、输出(1)、错误(2)之后的句柄 3 作为连接句柄,跑了一下,似乎什么也没有发生:
![用 shell 脚本做 tcp 协议模拟](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230605/1707550-20201124134828692-1592037169.png)
好在 Windows 上有 procexp 工具,可以查看进程创建的所有 tcp 连接:
![用 shell 脚本做 tcp 协议模拟](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230605/1707550-20201124135052804-866392507.png)
看起来这个连接确实建立成功了。当然你也可以用 windows 上的 netstat 命令查看:
;gutter:false;
C:\Users\yunh>netstat -no
活动连接
协议 本地地址 外部地址 状态 PID
TCP 10.2.56.38:1993 10.100.200.2:10003 ESTABLISHED 10320
TCP 10.2.56.38:2346 175.27.0.15:80 ESTABLISHED 14808
TCP 10.2.56.38:2474 121.51.139.161:8080 ESTABLISHED 15092
TCP 10.2.56.38:3147 10.2.56.13:7680 ESTABLISHED 8816
TCP 10.2.56.38:3576 47.97.243.182:80 ESTABLISHED 11292
TCP 10.2.56.38:3602 10.0.24.13:28888 ESTABLISHED 16224
TCP 10.2.56.38:3720 113.96.233.143:443 ESTABLISHED 15252
TCP 10.2.56.38:5006 10.2.61.20:7680 ESTABLISHED 8816
TCP 10.2.56.38:5022 10.2.25.16:7680 ESTABLISHED 8816
TCP 10.2.56.38:5303 49.232.126.211:443 ESTABLISHED 11292
TCP 10.2.56.38:6182 10.0.109.249:443 ESTABLISHED 16168
TCP 10.2.56.38:6183 10.0.109.249:443 ESTABLISHED 16168
TCP 10.2.56.38:6357 52.11.109.209:443 ESTABLISHED 11292
TCP 10.2.56.38:6697 40.90.189.152:443 ESTABLISHED 5268
TCP 10.2.56.38:7065 117.18.237.29:80 CLOSE_WAIT 4724
TCP 10.2.56.38:7100 220.170.53.122:443 TIME_WAIT 0
TCP 10.2.56.38:7113 220.181.174.166:443 TIME_WAIT 0
TCP 10.2.56.38:7117 180.163.150.166:443 ESTABLISHED 11292
TCP 10.2.56.38:7135 140.143.52.226:443 TIME_WAIT 0
TCP 10.2.56.38:7141 10.0.24.13:8888 CLOSE_WAIT 16224
TCP 10.2.56.38:7143 101.201.169.146:443 TIME_WAIT 0
TCP 10.2.56.38:7144 103.15.99.107:443 TIME_WAIT 0
TCP 10.2.56.38:7148 203.119.214.115:443 TIME_WAIT 0
TCP 10.2.56.38:7149 61.151.167.89:443 TIME_WAIT 0
TCP 10.2.56.38:7150 203.119.169.141:443 TIME_WAIT 0
TCP 10.2.56.38:7151 203.119.144.59:443 TIME_WAIT 0
TCP 10.2.56.38:7159 114.55.187.58:443 ESTABLISHED 11292
TCP 10.2.56.38:7160 42.121.254.191:443 TIME_WAIT 0
TCP 10.2.56.38:7162 118.178.109.187:443 TIME_WAIT 0
TCP 10.2.56.38:7165 47.110.223.99:443 TIME_WAIT 0
TCP 10.2.56.38:7166 116.62.93.118:443 TIME_WAIT 0
TCP 10.2.56.38:7195 123.150.76.171:80 CLOSE_WAIT 10772
TCP 10.2.56.38:6974 ################## ESTABLISHED 10984
TCP 10.2.56.38:7215 192.168.0.9:80 CLOSE_WAIT 4700
TCP 10.2.56.38:7218 10.2.100.217:7680 SYN_SENT 8816
TCP 10.2.56.38:7219 192.168.56.1:7680 SYN_SENT 8816
TCP 10.2.56.38:7680 10.2.102.27:53199 ESTABLISHED 8816
TCP 10.2.56.38:9763 192.168.23.23:49156 ESTABLISHED 4600
TCP 10.2.56.38:10267 125.39.132.161:80 ESTABLISHED 10772
TCP 10.2.56.38:10816 60.205.204.27:80 ESTABLISHED 10872
TCP 127.0.0.1:443 127.0.0.1:7216 ESTABLISHED 8108
TCP 127.0.0.1:2002 127.0.0.1:2003 ESTABLISHED 11292
TCP 127.0.0.1:2003 127.0.0.1:2002 ESTABLISHED 11292
TCP 127.0.0.1:2013 127.0.0.1:2014 ESTABLISHED 9600
TCP 127.0.0.1:2014 127.0.0.1:2013 ESTABLISHED 9600
TCP 127.0.0.1:2015 127.0.0.1:2016 ESTABLISHED 12948
TCP 127.0.0.1:2016 127.0.0.1:2015 ESTABLISHED 12948
TCP 127.0.0.1:2040 127.0.0.1:2041 ESTABLISHED 13960
TCP 127.0.0.1:2041 127.0.0.1:2040 ESTABLISHED 13960
TCP 127.0.0.1:2109 127.0.0.1:2110 ESTABLISHED 15092
TCP 127.0.0.1:2110 127.0.0.1:2109 ESTABLISHED 15092
TCP 127.0.0.1:2349 127.0.0.1:50051 ESTABLISHED 6308
TCP 127.0.0.1:2566 127.0.0.1:30031 ESTABLISHED 10624
TCP 127.0.0.1:3032 127.0.0.1:3033 ESTABLISHED 20276
TCP 127.0.0.1:3033 127.0.0.1:3032 ESTABLISHED 20276
TCP 127.0.0.1:3517 127.0.0.1:3518 ESTABLISHED 18200
TCP 127.0.0.1:3518 127.0.0.1:3517 ESTABLISHED 18200
TCP 127.0.0.1:3768 127.0.0.1:3769 ESTABLISHED 14076
TCP 127.0.0.1:3769 127.0.0.1:3768 ESTABLISHED 14076
TCP 127.0.0.1:3854 127.0.0.1:3855 ESTABLISHED 17380
TCP 127.0.0.1:3855 127.0.0.1:3854 ESTABLISHED 17380
TCP 127.0.0.1:4895 127.0.0.1:4896 ESTABLISHED 15524
TCP 127.0.0.1:4896 127.0.0.1:4895 ESTABLISHED 15524
TCP 127.0.0.1:5320 127.0.0.1:5321 ESTABLISHED 16736
TCP 127.0.0.1:5321 127.0.0.1:5320 ESTABLISHED 16736
TCP 127.0.0.1:6688 127.0.0.1:10803 ESTABLISHED 10872
TCP 127.0.0.1:6688 127.0.0.1:10824 ESTABLISHED 10872
TCP 127.0.0.1:6688 127.0.0.1:10841 ESTABLISHED 10872
TCP 127.0.0.1:6688 127.0.0.1:10849 ESTABLISHED 10872
TCP 127.0.0.1:6689 127.0.0.1:10819 ESTABLISHED 10672
TCP 127.0.0.1:7187 127.0.0.1:443 TIME_WAIT 0
TCP 127.0.0.1:7216 127.0.0.1:443 ESTABLISHED 10548
TCP 127.0.0.1:8419 127.0.0.1:8420 ESTABLISHED 14716
TCP 127.0.0.1:8420 127.0.0.1:8419 ESTABLISHED 14716
TCP 127.0.0.1:10803 127.0.0.1:6688 ESTABLISHED 2256
TCP 127.0.0.1:10819 127.0.0.1:6689 ESTABLISHED 13436
TCP 127.0.0.1:10824 127.0.0.1:6688 ESTABLISHED 10672
TCP 127.0.0.1:10841 127.0.0.1:6688 ESTABLISHED 15448
TCP 127.0.0.1:10849 127.0.0.1:6688 ESTABLISHED 9772
TCP 127.0.0.1:30031 127.0.0.1:2566 ESTABLISHED 10608
TCP 127.0.0.1:50051 127.0.0.1:2349 ESTABLISHED 10608
TCP [::1]:5900 [::1]:5901 ESTABLISHED 10548
TCP [::1]:5901 [::1]:5900 ESTABLISHED 10548
TCP [::1]:7188 [::1]:8307 FIN_WAIT_2 8108
TCP [::1]:7217 [::1]:8307 ESTABLISHED 8108
TCP [::1]:8307 [::1]:7188 CLOSE_WAIT 8108
TCP [::1]:8307 [::1]:7217 ESTABLISHED 8108
这里主要是通过过滤进程 ID 来实现快速定位的。连接也可以被主动关闭,这需要使用下面的重定向语法(其实就是关闭普通文件):
bash;gutter:false;
exec N < &-
其中 N 就是刚才打开的文件句柄,可以用 > 等效替换
Original: https://www.cnblogs.com/goodcitizen/p/monitor_protocol_on_tcp_by_shell.html
Author: goodcitizen
Title: 用 shell 脚本做 tcp 协议模拟
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/577599/
转载文章受原作者版权保护。转载请注明原作者出处!