33

We have a very simple tcp messaging script that cats some text to a server port which returns and displays a response.

The part of the script we care about looks something like this:

cat someFile | netcat somehost 1234

The response the server returns is 'complete' once we get a certain character code (specifically &001C) returned.

How can I close the connection when I receive this special character?

(Note: The server won't close the connection for me. While I currently just CTRL+C the script when I can tell it's done, I wish to be able to send many of these messages, one after the other.)

(Note: netcat -w x isn't good enough because I wish to push these messages through as fast as possible)

SCdF
  • 57,260
  • 24
  • 77
  • 113
  • Is `&001C` a 16 bit Unicode codepoint or is it just the ASCII character `0x1C` ? – caf Aug 13 '09 at 22:58

5 Answers5

16

Create a bash script called client.sh:

#!/bin/bash

cat someFile

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

Then invoke netcat from your main script like so:

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

(You'll need bash version 3 for the regexp matching).

This assumes that the server is sending data in lines - if not you'll have to tweak client.sh so that it reads and echoes a character at a time.

caf
  • 233,326
  • 40
  • 323
  • 462
  • 1
    Commenting on an old answer, but my version of nc (1.10) needs -e instead of -c (and then this works nicely for me). Also, a nit-pick: I'd avoid invoking `printf` each time through the loop, preferring to set a variable to the regular expression once. For example: `re=$'.*\x1C.*'` ... then use `[[ $FOO =~ $re ]]` as the conditional. – sjnarv Jun 20 '15 at 19:21
11

How about this?

Client side:

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

Testing:

# 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.

Client side produces:

    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

After 'J' appears, server side closes & prints 'closed...', ensuring that the connection has indeed closed.

anishsane
  • 20,270
  • 5
  • 40
  • 73
7

Try:

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

This requires GNU sed.

How it works:

{
    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
}

Note that this assumes there'll be a newline after \x01 - sed won't see it otherwise, as sed operates line-by-line.

bdonlan
  • 224,562
  • 31
  • 268
  • 324
3

Maybe have a look at Ncat as well:

"Ncat is the culmination of many key features from various Netcat incarnations such as Netcat 1.x, Netcat6, SOcat, Cryptcat, GNU Netcat, etc. Ncat has a host of new features such as "Connection Brokering", TCP/UDP Redirection, SOCKS4 client and server supprt, ability to "Chain" Ncat processes, HTTP CONNECT proxying (and proxy chaining), SSL connect/listen support, IP address/connection filtering, plus much more."

http://nmap-ncat.sourceforge.net

3

This worked best for me. Just read the output with a while loop and then check for "0x1c" using an if statement.

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