EDA365电子论坛网

标题: 怎样用bash做个tcp客户端 [打印本页]

作者: pulbieup    时间: 2020-3-19 10:02
标题: 怎样用bash做个tcp客户端
8 m8 T# x, {) w2 H9 j7 y
日常做后台服务开发,总免不了要写测试客户端。但是tcp客户端写起来其实还是比较罗嗦的,各种错误返回,各种异常判断。。。。而我们通常并不是要写一个健壮的客户端,我们只是要一个能用的客户端来测试服务端是否正确。% T! H4 l" {6 {
    这里给大家介绍一个简单易用的方法:用bash操作socket!很酷,是不是?! l# @2 u" M: y) f" `9 c
9 O, w- ?0 H1 R# o" l9 S: ?3 W/ q
" T% ]" e+ U/ i+ \7 l1 Q' z
    man bash,查找tcp关键字,可以看到这么一段内容:
8 D' `" Q' D5 _5 q) Z7 n1        /dev/tcp/host/port( S. S1 ^! Z4 `, f/ S3 N
2               If host is a valid hostname or Internet address, and port is an integer port number or service  name,  bash attempts to open a TCP connection to the corresponding socket., v- H8 L$ B. ]3 e& Q1 W

& Z1 t$ h+ @0 e+ S    把其中的host和port换成我们要连接的IP和端口,就可以用来建立tcp连接了。如下:
* `0 g1 E7 T  x  i
5 J) x) S( X0 `/ k. k1        exec 3<>/dev/tcp/10.6.221.149/9865# V; n  O! |5 E! j
2 Z( t5 x7 i$ f2 \3 G

0 t8 H% k  v3 x2 R$ y  n    上面就建立了一个到10.6.221.149:9865的可读可写的socket连接。
1 k( e) l2 m( l  P3 N    其中3就是指定的连接后的socket fd,由于0、1、2分别被stdin、stdout、stderr占用,所以可用fd最小从3开始。& l! ]: t- F7 D5 Q% \$ b- t
    ip换成域名其实也是支持的,比如
( H( n, @, `8 Y. Y( Z. {9 `4 N, k% I
1        exec 3<>/dev/tcp/www.xx.com/9865     注意"<>"前后不要空格,否则会出错。
# |, X' I' Q4 r0 h+ \# |
& }6 D. `) n% z4 J. B: i    发送请求其实很简单,就跟往文件里写数据一样。例如
+ S7 h2 Z6 i: k! m9 o7 k
" j! e+ P1 Y' ], R! b) j, ?1        exec "hello world." >&3
5 u1 ~# j5 v" C
3 y$ J* r$ P6 j/ j7 z: K6 x* q5 Z, d- _2 S2 k
    如果要发HTTP请求,那可以这样:
+ ]# |3 i7 H0 C" G2 Z" v
( ]8 [" p/ {- R1        echo -e "GET /crossdomain.xml HTTP/1.1\r\nHost:www.xx.com\r\n\r\n" >&3, f7 t( C) o; n' y+ z0 L& x

, r& p0 v7 Q- G/ n/ M$ g" |) z2 j% m) o$ a! Y1 c! A
     二进制请求可以这样发:0 ^% [4 ~1 F' g( _, w6 S

0 Q' y! `( U3 m: c2 n( B, n. c1        cat bin_data >&3* A3 V3 P$ V& y0 _/ P; `) g5 c7 [

  G3 y6 w# y* Z/ e# G! @& r
2 f5 W+ C% w. `    其中bin_data是已经写好的二进制包数据文件。5 g4 P6 X  @- r6 t% ]4 {6 n

* D( ]& a8 H# P; w7 S   读取服务器响应跟读文件差不多,可以这样写:
$ ^3 t4 M8 J3 L8 @( @2 i/ ]( Z1 D( O% E/ }  A
. \5 t0 F4 A* P7 [0 h
1        cat <&3
1 M; |9 K% F+ ~1 [3 I  ?# \: t/ Z* ]2 E: u4 m$ {
" m5 o5 Y8 |- s/ ^! B
    后台关闭连接以后,cat命令会自动结束。
1 ?1 k1 y, W( [% i( u5 q4 W
4 [2 K! ~% j- {4 U
: W+ b& m/ d8 l, q8 G7 P+ g    如果是读取的二进制内容,可以用hexdump来查看。
; S9 R: F1 P. m9 r* u! z7 g
( ^& x5 p1 e1 v2 e! y0 e- p; f- Z4 |' q/ t" W3 y
1        hexdump -C -n 31 <&30 u( h& p% w: L# O- H, e9 Y
; {+ \6 F5 O. f( J
& z# y3 A' A6 {( ~/ S' C: `
    读出来效果如下:7 H' {" S, A4 @# ~* _* {
5 I, ~) Q6 l- l/ C# @( s, S: H7 z
    8 d- |% G6 A. ?! R1 M5 X9 E3 j
2 `7 x. J$ V4 g3 k+ E3 o+ n
    其中-n是指示hexdump读31个字节就结束。! ^* c6 T' h* [6 x9 O

7 x9 f9 B1 J+ ?; _: d    一个好的编程习惯,建立了连接要记得关闭。
! W. i9 p9 g6 l# s2 `2 i1 M. Q    要关闭上面的socket连接可以这么写:% j; t" x2 j  G9 o* K0 C5 y
1        exec 3>&- # 关闭写,不能再发请求
) E3 B2 s! X; o& p8 {+ ?* c2 e2        exec 3<&- # 关闭读,不能再有返回     当然,你不关闭其实也不一定有啥大问题,bash脚本执行结束,该连接会自动被关闭。
9 p' A7 K, w6 x% Z( _* X# k
( k% J6 t) D8 B' d8 z    下面是我测试用的一个客户端:
5 ]* Z' k7 u5 s1        #!/bin/sh
) I" Y% j" n/ {  V% c% [2        exec 3<>/dev/tcp/10.6.221.149/9865" }. S# P. J9 R+ \% l2 w0 t
3        echo "<policy-file-request>" >&3! n6 X  ^* i: Z
4        cat <&3
9 v" M. r* d6 q- S4 |; ?  X' |1 M    瞧,这样的tcp客户端比C语言捣鼓出来的客户端代码少得不是一星半点啊。) [7 k2 p9 T; U; T
3 d3 U3 i  e" ^: w0 n
    用bash操作udp也差不多的,如法炮制试试吧。
. w! X( Z0 s$ h( U0 \    当然,如果你很能捣鼓,还可以用bash写个服务端试试,捣鼓出来记得把代码分享给我看看。
+ }' s1 c3 m& L  M+ a& x
作者: NNNei256    时间: 2020-3-19 18:18
用bash做个tcp客户端




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2