LINUX GAZETTE
[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]

"Linux Gazette...making Linux just a little more fun!"


Play with the Lovely Netcat:
Reinvent /usr/bin/yes

By zhaoway


Netcat and Yescat

The first but secondary purpose of this article is to introduce you this nifty networking tool: /usr/bin/netcat which is well available from the Debian GNU/Linux under the package name netcat. (The drill: apt-get install netcat and you're done.) There are very well written companion documentation by the anonymous software author, and from which a well formatted Unix manual page by my fellow Debian developers. Reading the companion documentation is really an interesting experience. It would almost certainly reminds the gentle reader that there is truly this kind of creature called Unix gurus living somewhere at the large. That kind of hackish feeling, think it, insists on and successful in being anonymous, after written such an excellent piece of software. Only true Unix guru could do that!

Since the netcat documentation is of such excellent quality, I will not duplicate it here. (However, I recommend you read the netcat documentation before reading this article.) For those of you with little patience, netcat could forward data stream from stdin to a TCP or UDP socket, and from a TCP or UDP socket to stdout. Just like the cat program to forward data from stdin to stdout. According to unconfirmed sources, that's the origin of the netcat program name.

The second but primary purpose of this article is to show you how tedious and clueless an article author (like me) can be, introducing a piece of software which does not have any graphical user interface, or any interactive help system. Ya know, I would simply go crazy if I cannot capture a screenshot or two!

So here we introduce the nutty yescat for a purpose which will show itself later: /usr/bin/yes. Nearly nobody even noticed it. But it quietly lies there in a corner of /usr/bin for so long that nearly none of us latecomers to the Linux world ever noticed it in any of our Linux systems. Its origin remains a mystery. Its popularity is just as /sbin/init! What does it do? Lets' see for our own eyes:

zw@q ~ % yes
y
y
y
y
y
y
y

Isn't it wonderful? ;-) (Press ctrl-C to stop the y's, otherwise they'll march down the screen forever.) It can even say no too!

zw@q ~ % yes no
no
no
no
no
no

In the following sections we will develop two companion utilities with which we will eventually reinvent /usr/bin/yes with the help from /usr/bin/netcat of course! Lets' start the journey now!

Hub and cable

The hub (hub.c) and cable (cable.c) utilities are certainly inspired by netcat which could forward data stream from a socket to stdout, and from stdin to a socket. Did I forget to recommend the netcat companion documentation for you to read? ;-) Hub is designed to be like a server, and cable is designed to be like a client. Instead of forwarding data between stdin/stdout and a socket, hub and cable forward and multiplex data from a socket to any other sockets. That's where the names come from. They're just like Ethernet hub and cable. Lets' see a screenshot. Yeah, screenshot! ;-)

zw@q ~ % ./hub
lullaby internetworks lab: (server alike) hub $Revision: 1.2 $
Copyright (C) 2001  zhaoway <zw@debian.org>

Usage: hub [hub buffer size] [tcp port number] [number of hub ports]

o hub buffer size is in bytes. for example 10240.
o tcp port number is at least 1024 so i do not need to be root.
o number of hub ports is at least 2. happy.
zw@q ~ %

Hub will listen on a TCP port simulating a many port Ethernet hub. Data come in from one hub port will be forwarded to other hub ports. You could test the hub alone without cable using netcat. Note: nc is the acronym for netcat.

  1. Launch hub in the console A: ConA % ./hub 10240 10000 2
  2. From console B, connect a netcat: ConB % nc localhost 10000
  3. From console C, connect another netcat: ConC % nc localhost 10000
  4. Then you could type in ConC and read the output in ConB, vice versa.

Then there is cable:

zw@q ~ % ./cable
lullaby internetworks lab: (client alike) cable $Revision: 1.2 $
Copyright (C) 2001  zhaoway <zw@debian.org>

Usage: cable [cable buffer size] [1st ip] [1st port] [2nd ip] [2nd port] ..

o cable buffer size is in bytes. for example 10240.
o ports should be listening or connection attempts will fail.
o number of ip addr and port pairs is at least 2.
zw@q ~ %

Cable is more or less like a shared Ethernet bus coaxial cable. It forwards and multiplexes data between listening socket daemons. Let's test it too.

  1. Launch a netcat daemon in ConA: ConA % nc -l -p 10000
  2. Launch another netcat daemon in ConB: ConB % nc -l -p 10001
  3. Arrange the cable: ConC % ./cable 10240 127.0.0.1 10000 127.0.0.1 10001
  4. Then you could type in ConA and read the output from ConB, vice versa.

There are some interesting techniques used in developing hub and cable. Notably the select() function call. But for now, we will focus on our course to reinvent the /usr/bin/yes first. ;-)

Reinvent the wheel

It's not a very easy task to reinvent /usr/bin/yes using netcat and hub and cable. I could only give a cheat answer. And that's why I need to set the buffer size command line argument. But anyway, let's begin!

The main idea is as following. First we set up a three-port hub, then we using cable to connect two hub port together, after that we could using netcat to echo any character into the remain free hub port. It's like the following diagram:

            |            cable
           \|/        ,---------,
            |         |         |
            V         V         V
	,--[ ]-------[ ]-------[ ]--.
        |   A         B         C   |
        |       three-port hub      |
	`---------------------------'

Because the nature of the hub, data sent in from port A, will be forwarded to port B and port C, since port B and C are connected by a cable, the data come out of the hub will go right back in, and then being multiplexed and forwarded to port A and circulating in the cable loop to eternity. Eventually port A will receive infinite copies of the original data sent in.

Lets' construct the device.

  1. In ConA, we launch the three-port hub: ConA % ./hub 10240 10000 3
  2. In ConB, we loop the cable: ConB % ./cable 10240 127.0.0.1 10000 127.0.0.1 10000

Now after we finished construction of our device, then we will using netcat to finally finish our reinvention of /usr/bin/yes.

ConC % echo "y" | nc localhost 10000
y
y
y
y
y
y

The tricky exercises left for the reader is: what if we change the buffer size of both cable and hub from 10240 to 1? You could try and see for yourself.

Have fun and good luck!

zhaoway

zhaoway lives in Nanjing, China. He divides his time among his beautiful girlfriend, his old Pentium computer, and pure mathematics. He wants to marry now, which means he needs money, ie., a job. Feel free to help him come into the sweet cage of marriage by providing him a job opportunity. He would be very thankful! He is also another volunteer member of the Debian GNU/Linux project.


Copyright © 2002, zhaoway.
Copying license http://www.linuxgazette.net/copying.html
Published in Issue 74 of Linux Gazette, January 2002

[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]