5.16 Shutdown of Server HostThe previous two sections discussed the crashing of the server host, or the server host being unreachable across the network. We now consider what happens if the server host is shut down by an operator while our server process is running on that host.
When a Unix system is shut down, the
init
process normally sends the
SIGTERM
signal to all processes (we can catch this signal), waits some fixed amount of time (often between 5 and 20 seconds), and then sends the
SIGKILL
signal (which we cannot catch) to any processes still running. This gives all running processes a short amount of time to clean up and terminate. If we do not catch
SIGTERM
and terminate, our server will be
|
5.17 Summary of TCP Example
Before any TCP client and server can communicate with each other, each end must specify the socket pair for the connection: the local IP address, local port, foreign IP address, and foreign port. In Figure 5.15, we show these four values as bullets. This figure is from the client's perspective. The foreign IP address and foreign port must be specified by the client in the call to
connect
. The two local values are normally
Figure 5.15. Summary of TCP client/server from client's perspective.
As we mentioned in Section 4.10, the client can obtain the two local values chosen by the kernel by calling getsockname after the connection is established. Figure 5.16 shows the same four values, but from the server's perspective. Figure 5.16. Summary of TCP client/server from server's perspective.
The local port (the server's well-known port) is specified by
bind
. Normally, the server also specifies the wildcard IP address in this call. If the server binds the wildcard IP address on a
|
5.18 Data FormatIn our example, the server never examines the request that it receives from the client. The server just reads all the data up through and including the newline and sends it back to the client, looking for only the newline. This is an exception, not the rule, and normally we must worry about the format of the data exchanged between the client and server. Example: Passing Text Strings between Client and Server
Let's modify our server so that it still reads a line of text from the client, but the server now expects that line to contain two integers separated by white space, and the server returns the sum of those two integers. Our client and server
main
functions
Figure 5.17
str_echo
function that adds two
|
|||||||||||||||||||
|
solaris % :tcpcli09 12.106.32.254 |
|
|
11 22 |
we type this |
|
33 |
this is the server's reply |
|
-11 -44 |
|
|
-55 |
But when the client and server are on two machines of different architectures (say the server is on the big-endian SPARC system freebsd and the client is on the little endian Intel system linux ), it does not work.
|
linux % tcpcli09 206.168.112.96 |
|
|
1 2 |
we type this |
|
3 |
and it works |
|
-22 -77 |
then we type this |
|
-16777314 |
and it does not work |
The problem is that the two binary integers are sent across the socket in little-endian format by the client, but interpreted as big-endian integers by the server. We see that it appears to work for positive integers but fails for negative integers (see Exercise 5.8). There are really three potential problems with this example:
Different
Different implementations can store the same C datatype differently. For example, most 32-bit Unix systems use 32 bits for a long but 64-bit systems typically use 64 bits for the same datatype (Figure 1.17). There is no guarantee that a short , int , or long is of any certain size.
Different implementations pack structures differently, depending on the number of bits used for the various datatypes and the alignment restrictions of the machine. Therefore, it is never wise to send binary structures across a socket.
There are two common solutions to this data format problem:
Pass all numeric data as text strings. This is what we did in Figure 5.17. This assumes that both hosts have the same character set.
Explicitly define the binary formats of the supported datatypes (number of bits, big- or little-endian) and pass all data between the client and server in this format. RPC packages normally use this technique. RFC 1832 [Srinivasan 1995] describes the External Data Representation (XDR) standard that is used with the Sun RPC package.