[How2Tips] Share files on the local network with socat

Important: some basic systems & networking knowledge is required in this article.

You’ve certainly already faced this use case: you just want to share some file with a coworker, but emailing it to them seems so overkill and frustrating when they’re sitting right next to you. Cheer up, we’ve got just the right thing for you!

We’ll use the socat utility to achieve our goal. socat is a simple yet powerful tool that allows for setting up a bidirectional exchange channel between 2 endpoints. An «endpoint» can basically be anything: the result of reading a file, a TCP or UDP socket, and much more.

Installation and basic operation

First, you’ll need to install the socat package; on Debian/Ubuntu, type this command in your terminal:

sudo apt-get install socat

The socat command’s usage is pretty straight-forward:

socat [options] <address> <address>

(address parameters are the «endpoints» we talked about earlier.)

Note: we said earlier that socat establishes a bidirectional communication by default, but for simplicity’s sake, we’ll use unidirectional communication only in the following examples, by systematically passing the -u option to the socat command.

So, for starters, let’s play with a very simple example. Type the following command in your terminal:

socat -u EXEC:'echo The meaning of life is 42' STDOUT

(This just prints The meaning of life is 42 in your terminal.)

In unidirectional mode, the leftmost address is the «source» (the reader), and the rightmost one is the «destination» (the writer). So, what we just ordered socat to do here is: read the result of executing echo The meaning of life is 42, and write it to STDOUT. Pretty simple right?

Sharing a file over the network

Now, back to our original subject. The conventional way to exchange content over a regular IP network is by opening a socket on both communication ends. Sockets are just «doors» that you open on 2 computers so they can communicate with each other over the network. A socket is bound to an IP address and a port number. For example, when you run the Apache HTTP server on your machine, you actually open a listening socket on port 80 (by default).

So what we’ll do is that we’ll just write the content of our .vimrc file to a listening TCP socket, so that our coworker can connect to our machine and read it. To achieve that, type the following command in your terminal:

socat -u FILE:"${HOME}/.vimrc" TCP-LISTEN:5778,reuseaddr

(reuseaddr is just a handy option that allows for reusing a port number that was already used by socat before but is not fully closed yet.)

We now have a listening TCP socket on port 5778, which will basically echo the content of our .vimrc file to whoever connects to it first.

Now, the coworker you want to share this file with will need to know your IP address to connect to the opened socket. There are multiple ways to acquire this piece of information, we’re not going to list them all, but one of them is typing this command in your terminal:

ip a

The output will more or less look like this:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: wlp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether d0:57:7b:29:43:48 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.97/24 brd 192.168.1.255 scope global dynamic wlp1s0
       valid_lft 76907sec preferred_lft 76907sec
    inet6 fe80::520d:fcb:c1bb:a9cc/64 scope link 
       valid_lft forever preferred_lft forever

This is a list of all your machine’s available network interfaces and their respective parameters, the IP address being one of them. The vast majority of small-size local networks use 192.168.0 or 192.168.1 as network prefix, so you’ll generally have to look for a line starting with inet 192.168.; in this example, my IP address is 192.168.1.97.

So now, just ask your coworker to type the following command in their terminal (just replace the example IP address with your own, and choose a real path for the downloaded file):

socat -u TCP:192.168.1.97:5778 STDOUT > /path/to/downloaded/file

Which would be equivalent to saying: read the content output by the TCP socket opened at 192.168.1.97:5778, write it to STDOUT, and pipe the result to a file.

Voila, you just shared a file over the local network with only a few terminal commands!

Bonus

One last handy little trick: if the file you want to share is pretty big, it would be cool to have some kind of feedback concerning the download progress. You can use the pv utility to achieve that. On Debian/Ubuntu, install it by typing the following command in the terminal:

sudo apt-get install pv

Then, just pipe the fetched stream into pv before redirecting to a file:

socat -u TCP:192.168.1.97:5778 STDOUT | pv -r > /path/to/downloaded/file

(The -r option will display the current download bitrate in real time.)

There you go!

This article is from our internal knowledge base, we wanted to share it with you. ❤ Send us a KUDO-Tweet if this article has helped you !