Coding Challenge #79 - Socat
This challenge is to build your own version of the Unix command line tool socat
Hi this is John with this week’s Coding Challenge.
🙏 Thank you for being one of the 72,201 software developers who have subscribed, I’m honoured to have you as a reader. 🎉
If there is a Coding Challenge you’d like to see, please let me know by replying to this email📧
Coding Challenge #79 - Socat
This challenge is to build your own version of the Unix command line tool socat
. It’s name is a combination of the words SOcket CAT as it is in effect a version of cat
that works over socks too.
Socat
is a command line utility that establishes two bidirectional byte streams and transfers data between them. Because the streams can be constructed from a large set of different types of data sinks and sources. That can include:
Files
Pipes
Devices (serial line, pseudo-terminal, etc)
Sockets (UNIX, IP4, IP6 - raw, UDP, TCP)
SSL sockets
Proxy CONNECT connections
Basically anything Unix like operating systems treat as a file.
But before we get into the coding challenge, thank you to the IEEE for sponsoring this issue of Coding Challenges!
Subscribe and Stay Ahead in Tech with IEEE Learning Network!
Discover the latest trends and practical applications in the hottest tech topics with the IEEE Learning Network (ILN). Subscribe to our free newsletter and receive monthly updates on the newest continuing education resources and products. Get information on the latest courses, exclusive discounts, virtual events, and more to keep you at the forefront of your field as a successful technical professional!
If You Enjoy Coding Challenges Here Are Three Ways You Can Help Support It
Refer a friend or colleague to the newsletter. 🙏
Sign up for a paid subscription - think of it as buying me a coffee ☕️ twice a month, with the bonus that you also get 20% off any of my courses.
Buy one of my courses that walk you through a Coding Challenge.
The Challenge - Building Socat
In this coding challenge we’re going to build a clone of the socat
tool that can establish bidirectional streams between files, sockets and pipes.
We can learn more about socat
using the man socat
command:
Socat is a command line based utility that establishes two bidirectional byte streams and transfers data between them. Because the streams can be constructed from a large set of different types of data sinks and sources (see address types), and because lots of address options may be applied to the streams, socat can be used for many different purposes.
There are lot of options for the socat
tool, so do refer back to the man page as you need to throughout the coding challenge.
Step Zero
As I have a background working in C and C-like programming languages, Coding Challenges is zero indexed. As always in step zero your goal is to setup your programming environment of choice, sit, stand or lie in wherever you code best, accompanied by your beverage and/or fuel of choice!
Step 1
In this step your goal is to support forwarding a local port to a remote host and port. With socat
the command line to do that looks like this:
% socat - TCP4:eu.httpbin.org:80
This is going to open a TCP connection to the defined host and port.
We can check it’s worked by sending a hand-crafted HTTP request like so:
% socat - TCP4:eu.httpbin.org:80
GET /get HTTP/1.1
Host: eu.httpbin.org
Accept: */*
Be sure to send two newlines after the Accept
line. If it’s working you’ll see a response like this:
% socat - TCP4:eu.httpbin.org:80
GET /get HTTP/1.1
Host: eu.httpbin.org
Accept: */*
HTTP/1.1 200 OK
Date: Wed, 04 Dec 2024 15:14:35 GMT
Content-Type: application/json
Content-Length: 225
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "eu.httpbin.org",
"X-Amzn-Trace-Id": "Root=1-675071db-6bd70b51268fe7614cf2c9ff"
},
"origin": "90.242.53.77",
"url": "<http://eu.httpbin.org/get>"
}
OK, we won’t normally need to hand-craft HTTP requests, but sometimes it’s fun to understand how these things work. If you want to really dig into HTTP, check out RFC9110.
Step 2
In this step your goal is to support writing to a file. The command line for this looks like:
socat -u STDIO FILE:test.txt,create
To test it we can write to the file and check the file then contains what we want:
% socat -u STDIO FILE:test.txt,create
Hello Coding Challenges
% cat test.txt
Hello Coding Challenges
Note you’ll have to send an end of file to socat
to terminate the program. If you’re on a Unix-like operating system you can do that by entering: CTRL-D
. We’ve used cat to check the file contains the content we entered. By the way building your own cat is another Coding Challenge!
Step 3
In this step your goal is to extend your socat
clone to have enough features to support creating a simple network message collector. To do that you need to support the following command line:
% socat -u TCP4-LISTEN:3333,reuseaddr,fork OPEN:./test.log,creat,append
This will set up socat
to listen for TCP connections on port 3333, and fork a new instance for every incoming connection. Using this we can use socat
as a simple log aggregator, sending logs from one or more servers to a central server.
To check it’s working run your socat
and then use netcat
to send mock log files to it like so:
% for i in {1..10} ; do echo "Hello, Coding Challenges Log Message $i" | nc localhost 3333 -c; done
Your log file should then contain:
Hello, Coding Challenges Log Message 1
Hello, Coding Challenges Log Message 2
Hello, Coding Challenges Log Message 3
Hello, Coding Challenges Log Message 4
Hello, Coding Challenges Log Message 5
Hello, Coding Challenges Log Message 6
Hello, Coding Challenges Log Message 7
Hello, Coding Challenges Log Message 8
Hello, Coding Challenges Log Message 9
Hello, Coding Challenges Log Message 10
By the way, build your own netcat is also a coding challenge!
Step 4
In this step your goal is to support the exec option so we use it to follow a log file on a server and send it to the message collector. Once you’ve done that you should be able to start the message collector as before:
% socat -u TCP4-LISTEN:3333,reuseaddr,fork OPEN:./test.log,create,append
Start socat tailing the ‘log’ file we’re using to test:
% socat -u EXEC:'tail -f test.txt' TCP4:localhost:3333
And in another terminal simulate log messages being written to the file, i.e.:
% echo "Coding Challenges Log Message" > test.txt
% echo "Another Coding Challenges Log Message" > test.txt
Once that works, congratulations you’ve built quite a useful tool and learned about forking processes, reading and writing files as well as TCP connections in your programming language of choice!
Going Further
There are many other options for socat
. Have a read of the manual and see what else it can do. If you’ve never used UDP before that might be an interesting place to start.
Share Your Solutions!
If you think your solution is an example other developers can learn from please share it, put it on GitHub, GitLab or elsewhere. Then let me know via Twitter or LinkedIn or just post about it there and tag me. Alternately please add a link to it in the Coding Challenges Shared Solutions Github repo.
Request for Feedback
I’m writing these challenges to help you develop your skills as a software engineer based on how I’ve approached my own personal learning and development. What works for me, might not be the best way for you - so if you have suggestions for how I can make these challenges more useful to you and others, please get in touch and let me know. All feedback greatly appreciated.
You can reach me on Bluesky, Twitter, LinkedIn or through SubStack
Thanks and happy coding!
John