Using socat for a full-duplex stdin + stdout connection between two programs

It’s easy to redirect stdin and stdout between programs in a single direction, but full-duplex or bi-directional communication is more challenging. Rather than deal with named pipes or fancy versions of fork, we can let socat do the hard work for us.

This program first prints something to stdout and then reads a response on stdin. One might think of it as the client. The final output to STDERR is not manipulated, and serves to inform the user of what actually happened. Note that buffering can really ruin our day, so this code disables buffering of stdout and stderr.

$ cat print_then_read.pl
#!/usr/bin/perl
select STDERR;
$| = 1; # disable buffering
select STDOUT;
$| = 1;
print "print_then_read\n";
$line = <STDIN> ;
chomp $line;
print STDERR "print_then_read got ($line)\n";

This little program first reads something and then prints it back. Its behavior is like that of a single-threaded, one-shot server.


$ cat read_then_print.pl
#!/usr/bin/perl
select STDERR;
$| = 1;
select STDOUT;
$| = 1;
$line = <STDIN> ;
chomp $line;
print "read_then_print read ($line) and has printed it!\n";

And here is the output when properly wired together using socat:


$ socat exec:./print_then_read.pl exec:./read_then_print.pl
print_then_read got (read_then_print read (print_then_read) and has printed it!)

Nifty! I’m using this trick to enable writing a simplistic pair of client/server scripts that implement a challenge-response protocol. socat can later enable tunneling over SSL, SSH, gzip/unzip, or anything else one can imagine, it seems.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s