当响应返回特定字符后,我该如何关闭netcat连接?

33

我们有一个非常简单的TCP消息脚本,将一些文本发送到一个服务器端口,然后返回并显示响应。

我们关心的脚本部分看起来像这样:

cat someFile | netcat somehost 1234
服务器返回响应时,只有在收到特定字符代码(具体为&001C)时才是“完成”的状态。
当我收到这个特殊字符时,如何关闭连接?
(注意:服务器不会为我关闭连接。虽然我目前只是在脚本完成时通过CTRL+C来结束它,但我希望能够连续发送许多这样的消息。)
(注意:netcat -w x不够好,因为我希望尽可能快地推送这些消息。)

“&001C” 是一个16位Unicode码点还是只是ASCII字符“0x1C”? - caf
5个回答

16

创建一个名为 client.sh 的 bash 脚本:

#!/bin/bash

cat someFile

while read FOO; do
        echo $FOO >&3
        if [[ $FOO =~ `printf ".*\x00\x1c.*"` ]]; then
                break
        fi
done

然后在你的主脚本中像这样调用netcat:

3>&1 nc -c ./client.sh somehost 1234

(你需要bash版本3来进行正则表达式匹配)。

这假设服务器正在按行发送数据 - 如果不是,您将不得不调整client.sh,使其逐个字符读取并回显。


1
评论一下旧答案,但我的nc版本(1.10)需要-e而不是-c(然后这对我很有效)。另外,一个小问题:我会避免在每次循环中调用printf,而更喜欢将变量设置为正则表达式。例如:re=$'.*\x1C.*' ... 然后使用[[ $FOO =~ $re ]]作为条件。 - sjnarv

11

这个怎么样?

客户端:

awk -v RS=$'\x1c' 'NR==1;{exit 0;}'  < /dev/tcp/host-ip/port

测试:

# server side test script
while true; do ascii -hd; done | { netcat -l 12345; echo closed...;}
# Generate 'some' data for testing & pipe to netcat.
# After netcat connection closes, echo will print 'closed...'

# Client side:
awk -v RS=J 'NR==1; {exit;}' < /dev/tcp/localhost/12345
# Changed end character to 'J' for testing.
# Didn't wish to write a server side script to generate 0x1C.

客户端产生:

    0 NUL    16 DLE    32      48 0    64 @    80 P    96 `   112 p
    1 SOH    17 DC1    33 !    49 1    65 A    81 Q    97 a   113 q
    2 STX    18 DC2    34 "    50 2    66 B    82 R    98 b   114 r
    3 ETX    19 DC3    35 #    51 3    67 C    83 S    99 c   115 s
    4 EOT    20 DC4    36 $    52 4    68 D    84 T   100 d   116 t
    5 ENQ    21 NAK    37 %    53 5    69 E    85 U   101 e   117 u
    6 ACK    22 SYN    38 &    54 6    70 F    86 V   102 f   118 v
    7 BEL    23 ETB    39 '    55 7    71 G    87 W   103 g   119 w
    8 BS     24 CAN    40 (    56 8    72 H    88 X   104 h   120 x
    9 HT     25 EM     41 )    57 9    73 I    89 Y   105 i   121 y
   10 LF     26 SUB    42 *    58 :    74

在出现“J”后,服务器端会关闭并打印“closed...”,确保连接已经关闭。

2
当最高票答案不是我的,且没有被接受的答案时,我如何获得赏金? - anishsane

7

尝试:

(cat somefile; sleep $timeout) | nc somehost 1234 | sed -e '{s/\x01.*//;T skip;q;:skip}'

这需要使用GNU sed。
工作原理:
{
    s/\x01.*//; # search for \x01, if we find it, kill it and the rest of the line
    T skip;     # goto label skip if the last s/// failed
    q;          # quit, printing current pattern buffer
    :skip       # label skip
}

请注意,这里假设在\x01后面会有一个换行符。否则sed无法识别,因为sed是逐行操作的。

这样做不起作用,因为netcat会在cat关闭netcat的标准输入后立即关闭连接。 - caf
固定的,甚至带有超时 :) - bdonlan

3
也许您也可以看看Ncat:
"Ncat是各种Netcat版本的关键特性的集大成者,例如Netcat 1.x,Netcat6,SOcat,Cryptcat,GNU Netcat等。 Ncat具有许多新功能,例如“连接代理”,TCP / UDP重定向,SOCKS4客户端和服务器支持,能够“链接”Ncat进程,HTTP CONNECT代理(和代理链接),SSL连接/监听支持,IP地址/连接过滤等等。" http://nmap-ncat.sourceforge.net

3

对我来说,这是最好的方法。只需使用while循环读取输出,然后使用if语句检查“0x1c”的值即可。

while read i; do 
    if [ "$i" = "0x1c" ] ; then # Read until "0x1c". Then exit
        break
    fi
    echo $i; 
done < <(cat someFile | netcat somehost 1234)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接