Experiments with Sockets

Part I: Unix Domain Sockets

To find the process id of the X Server in our example we use the ps command, which returns 770.
For the client we find the process id (pid) instantly when we use the ampersand ('&') character to run
test to the background. This is 2079. Next we use the netstat command to find info sockets in the
system. Using a pipeline ('|') we pass the output to the 'grep' command to show only the sockets
of the process with pid 770, which is currently the X Server. At the first netstat of the following
image we use redirect ('>') the pass the output to file netstat1 and with the second we use a
pipeline to count the number of lines the output gave. This is 37.

The following image shows the output that netstat gave previously for the X Server, however
this time goes to xterm, instead of the file netstat1. The first two results represent tcp/ip
sockets, while the remaining represent UNIX sockets and are formatted as:

Proto RefCnt Flags Type State I-Node PID/Program name Path

From all UNIX socket with
/tmp/.X11-unix/X0 path we especially should notice the third, the one with
the larger (and possibly newer) inode number, 22510. This is the one as we show next that is
used by connection of test, the X client.

This is the time to find the socket info of the test part, where we find the inode number
22509, which is one number before 22510 of the X Server socket. This shows that the X client and
the X Server created their sockets about the same time, which is what we would expect. The X Client
is killed then, using the 'kill' command.

We repeat the previous steps to find the number of active sockets of the X Server, now that the
X Client is absent. The number of output is now 36, which is one less since test was
previously terminated. Also the new output of netstat is passed to file netstat2 in order to make
the comparison between netstat1 (which includes test) with netstat2. To do so we use the 'diff'
instruction, which shows that the socket with inode 22510 is missing at netstat2, as we
expected.

To have a look at the new output of netstat we run it without redirecting the output to netstat2.

Part II: TCP/IP Sockets

As with the UNIX Domain sockets we use netstat to gather information for the X client-server
connection at the socket interprocess communication layer. We use the same X client as previously
with the UNIX Domain sockets and we run it using the DISPLAY environment variable, which takes the
value 'tcp/192.168.1.101:0.0' to indicate the display 0, screen 0 (':0.0') in the host
192.168.1.101, which is anyway the same system with the client's. This time the connection is
made with the tcp protocol. The X client called 'test' runs from the current directory
(./) in the background as indicated again with the ampersand ('&') character and its pid is
1421:

DISPLAY=tcp/192.168.1.101:0.0 ./test &

Before this instruction the xhost was used to allow tcp/ip connections in our system from any
location:

sudo xhost +

We use the netstat as:

netstat -na -A inet

As we read in the netstat man page argument
-n show numerical addresses instead of trying to determine symbolic host, port or user names.
Also -a show both listening and non-listening sockets. Finally -A provides inet as the
address family of the connection, therefore no Unix Domain sockets are included in the output.

At the output we are interested in sockets where the one end (Local or Foreign address) has a
port number 6000, which as referred at
section 1.4.2 is the port number the X Server waits for new clients for display 0. We find
this category of sockets at lines 1, 4, 5 and 6 after the header:

Proto Recv-Q Send-Q Local Address Foreign Address State

The first socket represents the X Server's listening address for new client connections. As we
see under the 'State' header the sockets state is obviously LISTENING. The IP 0.0.0.0,
which is bound with port 6000, corresponds to the IP address INADDR_ANY, which as we saw in
section 1.4.2 represents any local IP
address of the host.

The socket at the fourth line after the header has at its Local Address the tcp/ip socket
192.168.1.101:51835. This is the socket of our X Client, which has an IP 192.168.1.101 and a port number
51838 and is connected (state is ESTABLISHED) with the X Server,
which uses the socket 192.168.1.101:6000, with the well known port number 6000. If the conclusion that this is indeed our X client seems flimsy we have to proceed to
the next to this figure, which verifies this hypothesis. Most of the times in the tcp/ip communication the client and the server are in different hosts and therefore the IP numbers are different. This is not the case however in this example, since we use the same Linux box for both client and server.

The next socket found at the fifth line has also a port number 6000 at the local address side.
Therefore it represents the X Server side. However we should not pay any special attention
since the socket state is TIME_WAIT and as we will explain next this is a socket at its final
stage, just before closed and it is the remnant of another similar with the current experiment
of a connection that after some seconds no longer exists.

The final socket with port number 6000 also in the ESTABLISHED state represents the X Server of
our connection since in the Local Address header is found the socket 192.168.1.101:6000.

This time we run netstat as:

netstat -ap --inet

where the --inet is similar to -A inet and the -p argument show the PID and name of the
program to which each socket belongs. This is 1421 and certainly the same as the one returned
in the previous figure when we started ./test. This leaves no doubt that this socket belongs
to our X Client.

At the next figure we run netstat twice as:

netstat -a --inet

The absence of argument -n in the current and in the previous image makes netstat to
try to determine symbolic host, port or user names. Therefore instead of 192.168.1.101:6000 the
X Server's port appears as ubuntu.local:x11 and the X client's port instead of
192.168.1.101:51835 appears as ubuntu.local:51835. The domain name in our system is
ubuntu.local and x11 is defined in /etc/services as the port number 6000.

The plan is to run netstat, then to use the 'kill' command to terminate
the X Client and then to run another time the netstat to see the transition of the X Client's
socket state from ESTABLISHED to TIME_WAIT, and certainly the disappearance of the X Server's
socket. The X client enters the TIME_WAIT state to ensure that all data have gone through. For
more info see Richard Stevens'
comment:
"The end that sends the first FIN goes into the TIME_WAIT state, because that is the end that sends the final ACK. If the other end's FIN is lost, or if the final ACK is lost, having the end that sends the first FIN maintain state about the connection guarantees that it has enough information to retransmit the final ACK."
Also see the diagram in this link.

As we see in the following figure the X Client after closed all open files (not in
our case) and sockets it finally terminates. The time elapsed after we entered the 'kill'
command, which started the closing process and the TIME_WAIT state, until the socket is closed
(and the client terminated) in my system was about 60 seconds. WE read from
this link:
"RFC 793 [Postel 1981] specifies the MSL as 2 minutes. Common implementation values, however,
are 30 seconds, 1 minute and 2 minutes."

As we read in
Programming Unix Sockets in C:
"The reason that the duration of the TIME_WAIT state is 2*MSL is that the maximum amount of time a packet can wander around a network is assumed to be MSL seconds. The factor of 2 is for the round-trip. The recommended value for MSL is 120 seconds, but Berkeley-derived implementations normally use 30 seconds instead.", where
MSL stands for Maximum Segment Lifetime.