Как я могу закрыть соединение netcat после того, как в ответе будет возвращен определенный символ?

У нас есть очень простой сценарий обмена сообщениями tcp, который передает некоторый текст на порт сервера, который возвращает и отображает ответ.

Та часть скрипта, которая нас интересует, выглядит примерно так:

cat someFile | netcat somehost 1234

Ответ, который возвращает сервер, считается «завершенным», как только мы получаем определенный код символа (в частности, &001C).

Как закрыть соединение при получении этого специального символа?

(Примечание: сервер не будет закрывать соединение для меня. Пока я просто нажимаю CTRL+C на скрипт, когда могу сказать, что это сделано, я хочу иметь возможность отправлять многие из этих сообщения, одно за другим.)

(Примечание: netcat -w x недостаточно, потому что я хочу отправить эти сообщения как можно быстрее)


person SCdF    schedule 13.08.2009    source источник
comment
Является ли &001C 16-битным кодом Unicode или это просто символ ASCII 0x1C?   -  person caf    schedule 14.08.2009


Ответы (5)


Создайте bash-скрипт с именем client.sh:

#!/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 так, чтобы он считывал и отображал символ за раз.

person caf    schedule 13.08.2009
comment
Комментируя старый ответ, но моя версия nc (1.10) требует -e вместо -c (и тогда это прекрасно работает для меня). Кроме того, придирка: я бы не стал вызывать printf каждый раз в цикле, предпочитая один раз устанавливать переменную в регулярное выражение. Например: re=$'.*\x1C.*' ... тогда используйте [[ $FOO =~ $re ]] в качестве условного предложения. - person sjnarv; 20.06.2015

Как насчет этого?

Сторона клиента:

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...», гарантируя, что соединение действительно закрыто.

person anishsane    schedule 14.06.2015
comment
Как я получил награду, если ответ с наибольшим количеством голосов не мой, и нет принятого ответа? - person anishsane; 03.07.2015

Пытаться:

(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 работает построчно.

person bdonlan    schedule 13.08.2009
comment
Это не сработает, потому что netcat закроет соединение, как только cat закроет стандартный ввод netcat. - person caf; 14.08.2009
comment
исправлено, даже с тайм-аутом :) - person bdonlan; 14.08.2009

Возможно, взгляните и на 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

person Community    schedule 13.08.2009

Это сработало лучше всего для меня. Просто прочитайте вывод с помощью цикла while, а затем проверьте наличие «0x1c» с помощью оператора if.

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