I have a scenario where multiple processes on the same box want to communicate with a serial device. Process A needs two-way communications with the serial port, and Process B only needs to be able to write to the serial port. The serial device is continually spewing data, while the two processes periodically write to the port. The environment is Cygwin on Windows (the processes are windows processes), but the serial port could be moved to a *nix virtual machine if anyone has a Linux-only solution.

My "network diagram" is as follows:

                                         /--<->--[Process A]
[serial device]-ttyS0--<->--[socat]-udp-<
                                         \--<<<--[Process B]

My first attempt was to set up a socat instance with udp-recvfrom and the fork option. This works for the first packet - a process forks off from socat, sends the data to the serial device, and starts reading data back from the serial device. However, this forked process now has the serial port open for read-write, so no more forks successfully start.

Can anyone think of any way to get this to work? I can think of the following avenues but I haven't found settings to make any of them work:

  • Use socat's udp-recv option to receive from anyone, but find a way to make it send replies to a specific address.
  • Use two unidirectional socats, one to write to the port and one to read from the port. I would then need a way to combine these two unidirectional streams into one bidirectional stream, but I don't know how.
  • This has an upvote... If you don't get an answer in the next day or two, and would like it moved to SU to see how it does there, please flag again at that time. Thank you! – Chris S Nov 28 '12 at 15:27

I found a solution. It involves 4 instances of socat, arranged in the network diagram below:

                               /-<-[A - udp receiver] <=udp= [D - udp sender]-<-\
ttyS0 <--> [B - serial adapter]                                                  [C - tcp adapter] <=tcp=> Process A
  • Socat "B" talks to the serial port, takes input on stdin and outputs to stdout.
  • Socat "A" listens for UDP packets from anywhere and outputs them over stdout, where they are piped into socat "B".
  • Socat "C" listens for a TCP connection from Process A. Data coming from socat "A" comes in stdin and is routed to Process A. Data from Process A is sent out stdout to socat "D".
  • Socat "D" takes data from stdin and sends it out over UDP to socat "A".

Process B sends UDP packets to socat "B" when it wants to inject traffic.

The bash command to create this monstrosity is as follows:

socat -d -d -d -lpA_udp_rxr -u -T5 udp-recv:1111 - 2>>log.txt |
socat -d -d -d -lpB_serial_adapter -t5 - /dev/ttyS0,raw 2>>log.txt |
socat -d -d -d -lpC_tcp_adapter -T5 - tcp4-listen:3333 2>>log.txt |
socat -d -d -d -lpD_udp_sender -u -T5 - udp:localhost:1111,sourceport=2222 2>>log.txt 

This also sets a timeout of 5 seconds and logs a lot of detail to "log.txt". Port numbers replaced for security.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.