Site hosted by Build your free website today!

Hands-on Projects for the Linux Graphics Subsystem

New book from Christos Karayiannis

Available in Amazon Kindle format at:

Experiments with Sockets

Part I: Unix Domain Sockets

We run the 'test' X Client (see section 1.5) as:

DISPLAY=unix/:0.0 ./test
DISPLAY=:0.0 ./test
or simply

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/' to indicate the display 0, screen 0 (':0.0') in the host, 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/ ./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, 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 This is the socket of our X Client, which has an IP and a port number 51838 and is connected (state is ESTABLISHED) with the X Server, which uses the socket, 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

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 the X Server's port appears as ubuntu.local:x11 and the X client's port instead of 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.

On the whole issue of TIME_WAIT see also TIME_WAIT and "port reuse".

Other tools to consider

Similar info with netstat we receive from lsof, which has the syntax:

lsof -i4 test
for tcp sockets and the syntax:
lsof -U test
for Unix domain sockets. If we run lsof after we start test we take the following results:

Another interesting utility, strace, is used in section 1.5 to x-ray the socket system calls (socket, setsockopt, e.t.c.) of test.