Search code examples
bashfifonetcat

Using netcat with FIFOs


I'm trying to get diagnostics data from a device to which I connect over the network. It offers a nice tight proprietary protocol where you send a 3 or 4 character request and receive a <~30 character response. Things to take into account:

  1. You must wait 20 ms between requests (I want to poll as fast as possible)
  2. You must wait for the response before sending the next request
  3. While the request must end in a Unix line end, the responses come with Mac line ends (I know)

I'm trying to do this with netcat. Basic operation is easy:

$ echo STA | netcat <IP> <Port>
123498754

The STA request will give you a status word that netcat writes to stdout. I can also do this:

$ cat | netcat <IP> <Port>
STA          # <- typed input
12345678     # written by netcat
STA          # <- typed input
12345678     # written by netcat

Here I can see that the first request takes considerably longer: multiple seconds versus no noticeable delay. I want to get rid of the delay. And so my quest begins: Keep netcat open!

I cannot just pipe a file into netcat, because I have to wait for the responses. So I'm trying to do this using FIFOs. I created two (/d/pc2dev and /d/dev2pc), both with rw permission. I could write a script based on that if I could get the basics working. This works:

#### SHELL 1 #############################
$ tail -f /d/pc2dev | netcat <IP> <Port> | tr '\r' '\n'
12345678654   # written by netcat with delay
12345678654   # written by netcat as soon as I send the request on shell 2
12345678654   # ditto
#### SHELL 2 #############################
$ echo STA > /d/pc2dev
$ echo STA > /d/pc2dev
$ echo STA > /d/pc2dev

(without the tr, responses will get written over one another.)

However, this does not:

#### SHELL 1 #############################
$ tail -f /d/pc2dev | netcat <IP> <Port> | tr '\r' '\n' > /d/dev2pc
#### SHELL 2 #############################
$ echo STA > /d/pc2dev
$ echo STA > /d/pc2dev
#### SHELL 3 #############################
$ cat /d/dev2pc
# expecting output here - none comes!

Writing to a normal file also doesn't work:

#### SHELL 1 #############################
$ tail -f /d/pc2dev | netcat <IP> <Port> | tr '\r' '\n' > log.txt
#### SHELL 2 #############################
$ echo STA > /d/pc2dev
$ echo STA > /d/pc2dev
$ cat log.txt
# nothing

It seems that the write operation to FIFO/file is buffered somewhere, while the write to stdout is done immediately. (However, even on ctrl+c'ing netcat et al., this hypothetical buffered output does not get written.)

Be it like that or otherwise - how can I get this to work?


Solution

  • try piping to tee instead of redirecting the output, man 1 tee, see what happens.

    The following worked

    $ tail -f /d/pc2dev | stdbuf -i0 -o0 netcat <IP> <Port> | stdbuf -i0 -o0 tr '\r' '\n' > /d/dev2pc