Chapter 5
5.1 | The duration of the TIME_WAIT state should be between 1 and 4 minutes, giving an MSL between 30 seconds and 2 minutes. |
5.2 | Our client/server programs do not work with a binary file. Assume the first 3 bytes in the file are binary 1, binary 0, and a newline. The call to fgets in Figure 5.5 reads up to MAXLINE-1 characters, or until a newline is encountered, or up through the EOF. In this example, it will read the first three characters and then terminate the string with a null byte. But, our call to strlen in Figure 5.5 returns 1, since it stops at the first null byte. One byte is sent to the server, but the server blocks in its call to readline, waiting for a newline character. The client blocks waiting for the server's reply. This is called a deadlock: Both processes are blocked waiting for something that will never arrive from the other one. The problem here is that fgets signifies the end of the data that it returns with a null byte, so the data that it reads cannot contain any null bytes. |
5.3 | 5.3 Telnet converts the input lines into NVT ASCII (Section 26.4 of TCPv1), which terminates every line with the two-character sequence of a CR (carriage return) followed by an LF (linefeed). Our client adds only a newline, which is actually a linefeed character. Nevertheless, we can use the Telnet client to communicate with our server as our server echoes back every character, including the CR that precedes each newline. |
5.4 | No, the final two segments of the connection termination sequence are not sent. When the client sends the data to the server, after we kill the server child (the "another line"), the server TCP responds with an RST. The RST aborts the connection and also prevents the server end of the connection (the end that did the active close) from passing through the TIME_WAIT state. |
5.5 | Nothing changes because the server process that is started on the server host creates a listening socket and is waiting for new connection requests to arrive. What we send in Step 3 is a data segment destined for an ESTABLISHED TCP connection. Our server with the listening socket never sees this data segment, and the server TCP still responds to it with an RST. |
5.6 | Figure E.1 shows the program. Running this program under Solaris generates the following:
The initial sleep of two seconds is to let the daytime server send its reply and close its end of the connection. Our first write sends a data segment to the server, which responds with an RST (since the daytime server has completely closed its socket). Note that our TCP allows us to write to a socket that has received a FIN. The second sleep lets the server's RST be received, and our second write generates SIGPIPE. Since our signal handler returns, write returns an error of EPIPE. |
5.7 | Assuming the server host supports the weak end system model (which we describe in Section 8.8), everything works. That is, the server host will accept an incoming IP datagram (which contains a TCP segment in this case) arriving on the leftmost datalink, even though the destination IP address is the address of the rightmost datalink. We can test this by running our server on our host linux (Figure 1.16) and then starting the client on our host solaris, but specifying the other IP address of the server (206.168.112.96) to the client. After the connection is established, if we run netstat on the server, we see that the local IP address is the destination IP address from the client's SYN, not the IP address of the datalink on which the SYN arrived (as we mentioned in Section 4.4).Figure E.1 Generate SIGPIPE.tcpcliserv/tsigpipe.c
|
5.8 | Our client was on a little-endian Intel system, where the 32-bit integer with a value of 1 was stored as shown in Figure E.2.Figure E.2. Representation of the 32-bit integer 1 in little-endian format.![]() Figure E.3. Representation of the 32-bit integer from Figure E.2 in big-endian format.![]() Figure E.4. Representation of the 32-bit integer - 22 in little-endian format.![]() |
5.9 | The technique is correct (converting the binary values to network byte order), but the two functions htonl and ntohl cannot be used. Even though the l in these functions once meant "long," these functions operate on 32-bit integers (Section 3.4). On a 64-bit system, a long will probably occupy 64 bits and these two functions will not work correctly. One might define two new functions, hton64 and ntoh64, to solve this problem, but this will not work on systems that represent longs using 32 bits. |
5.10 | In the first scenario, the server blocks forever in the call to readn in Figure 5.20 because the client sends two 32-bit values but the server is waiting for two 64-bit values. Swapping the client and server between the two hosts causes the client to send two 64-bit values, but the server reads only the first 64 bits, interpreting them as two 32-bit values. The second 64-bit value remains in the server's socket receive buffer. The server writes back one 32-bit value and the client will block forever in its call to readn in Figure 5.19, waiting to read one 64-bit value. |
5.11 | IP's routing function looks at the destination IP address (the server's IP address) and searches the routing table to determine the outgoing interface and next hop (Chapter 9 of TCPv1). The primary IP address of the outgoing interface is used as the source IP address, assuming the socket has not already bound a local IP address. |