Piping commands into nc

9,259

Solution 1

There are probably many ways to do this.

With netcat

The problem with netcat is that it closes the connection as soon as it detects an end-of-file. The GNU implementation of netcat does have a couple of options (-k or -w -1) to keep a listening instance open indefinitely, but neither works. What does work is nmap's version of netcat, called ncat.

On your pc, install the nmap package, then issue:

mkfifo return_pipe
ncat -k -l 12345 0<return_pipe| ncat -C 192.168.0.10 35000 1>return_pipe &

Now you can transfer everything you like, in many different bunches, by means of

echo Ciao | ncat localhost 12345
cat somefile.txt | ncat localhost 12345 

without the connection ever dropping, provided your listener cooperates (i.e., it does not quit listening after the first end-of-file). Or you can make this part simpler by using a named pipe: from a terminal different from the one where you issued the first command,

mkfifo mypipe
tail -f mypipe | ncat localhost 12345 &
echo Ciao > mypipe
cat somefile.txt > mypipe

The return message from you device is now in the named pipe return_pipe. The command

tail -f return_pipe >> responses

appends the device response to a file called responses.

Without netcat

This has been pointed out by Ipor Sircer (nice!, +1 from me). But I would do it slightly differently,

exec 3>/dev/tcp/192.168.0.10/35000
exec 4</dev/tcp/192.168.0.10/35000
exec 4>>somefile.out
echo "Ciao" >&3 
cat somefile.txt >&3

if you also want to keep track of your commands,

echo Ciao | tee  -a file_with_my_commands 1>&3
cat somefile.txt | tee -a file_with_my_commands 1>&3

and, when you are done with this communication,

exec 3>&-
exec 4>&-

Solution 2

Why do you use netcat? Bash can handle tcp sockets with builtin alias.

n=0
while read -r line;do
 ((n++))
 exec 3<>/dev/tcp/192.168.0.10/35000
 echo -e "$line" >&3
 cat <&3 > response.$n
 exec 3<&-
 exec 3>&-
done < data.txt
Share:
9,259

Related videos on Youtube

Markysm
Author by

Markysm

Updated on September 18, 2022

Comments

  • Markysm
    Markysm over 1 year

    I've seemingly searched many very similar questions but never quite found something to work. I'm trying to use a raspberry pi (2nd gen) to communicate with a Wifi OBDII sensor. I'm able to use the following command

    nc -C 192.168.0.10 35000
    

    192.168.0.10 is the car sensor and 35000 the port. It's not that relevant as connecting seems to be fine. Anyways, I can open a nc instance and then type, for example "0145" (a sensor code), and in return I get a value for that sensor back on the output of the nc session (for say, the RPM of my engine). That works fine. What i'd like to do is pipe commands from a text file into the nc session for plotting purposes. So my ideal result would be a constant stream of RPM values and associated times dumped into a text file. I can work from there. However, I don't exactly know how to do that. I've set up a commands.txt which is thousands of lines of "0145" and I'd like to read that file and pass it line by line to nc (I can probably control the sampling interval with sleep), and then read the output and stash those into a text file. I know this issue has something to do with stdin and stdout and piping, but for whatever reason, I haven't been able to quite get it. I am by no means a master at any of those. I'd also like to script the entire process.

    Right now, if i run

    cat <(echo 0145) - | nc -C 192.168.0.10 35000
    

    that gives me the output in the terminal that I want, but only works for a single value. But as soon as I try to put it into a loop, where I make that 0145 into $commands in the script and get $commands line by line from a txt file, it ceases to work. In fact, it stops working inside any loop or if block even if I leave it as 0145 and dont use a variable.

    So, long story short, I want to script sending a txt file line by line to a nc connection, and then I want to extract each response into another file. If it was unscripted, I can open that nc connection and send 0145 every 1 second and get those responses (still dont know how to pass them to a file), but thats hardly efficient. I feel like there should be an easier way to do this. I'm somewhat of a noob but figured id give it a shot here. Any help is greatly appreciated

  • Markysm
    Markysm over 7 years
    I gave that a shot, but I haven't quite gotten it doing what I need it to. Just to understand correctly: $line will be a given line from data.txt?
  • Ipor Sircer
    Ipor Sircer over 7 years
    yes. every lines will piped into the tcp socket, and every response will be stored at file respone.<linenumber>
  • Markysm
    Markysm over 7 years
    Oh hold up, I dont appear to have a /dev/tcp when I ls in /dev
  • Ipor Sircer
    Ipor Sircer over 7 years
    Because it's a builtin alias of bash.
  • Markysm
    Markysm over 7 years
    it's not quite where I need it to be for some reason but it's a huge step in the right direction. I've cut my data.txt file down to just 5 lines for simplicity (and so I dont get 1000 response files), but so far i've only been able to generate a single response.1 file (it doesn't seem to be looping)
  • Ipor Sircer
    Ipor Sircer over 7 years
    updated answer with closing socket. but the daemon on rpi should done it, or you can send a command to close the socket. it's not too healthy to force to close the socket.
  • Markysm
    Markysm over 7 years
    something is not quite right still, if im getting the code line by line, it is 1. reading a line from data.txt (not sure what -r does), 2. incrementing n 3. opening the socket 4. echoing $line to the socket (note that the commands need to be followed by a carriage return or a newline or something to that effect to register), 5. reading from the TCP socket 6/7 close the socket and loop. It isn't however looping still and in the terminal when I execute the script it hangs until I kill it
  • Markysm
    Markysm over 7 years
    also, its only writing what I inputted (the line from the data.txt) but not the response from the device (not sure if it isn't getting one or just not writing it). NVM, when I added the \r into the echo then it got a response. But still not looping