09.11.2016 Views

Foundations of Python Network Programming 978-1-4302-3004-5

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

CHAPTER 3 ■ TCP<br />

The foregoing example output is produced by having the client make one connection to the server,<br />

like this:<br />

$ python tcp_sixteen.py client<br />

Client has been assigned socket name ('127.0.0.1', 58185)<br />

The server said 'Farewell, client'<br />

You can see from the rest <strong>of</strong> the server code that, once a connected socket has been returned by<br />

accept(), it works exactly like a client socket with no further asymmetries evident in their pattern <strong>of</strong><br />

communication. The recv() call returns data as it becomes available, and sendall() is the best way to<br />

send a new string <strong>of</strong> data when you want to make sure that it all gets transmitted.<br />

You will note that an integer argument was provided to listen() when it was called on the server<br />

socket. This number indicates how many waiting connections, which have not yet had sockets created<br />

for them by accept() calls, should be allowed to stack up before the operating system starts turning new<br />

connections away by returning connection errors. We are using the very small value 1 here in our<br />

examples because we support only one example client connecting at a time; but we will consider larger<br />

values for this call when we talk about network server design in Chapter 7.<br />

Once the client and server have said everything that they need to, they close() their end <strong>of</strong> the<br />

socket, which tells the operating system to transmit any remaining data still left in their output buffer<br />

and then conclude the TCP session with the shutdown procedure mentioned previously.<br />

Address Already in Use<br />

There is one last detail in Listing 3–1 that you might be curious about: why is the server careful to set the<br />

socket option SO_REUSEADDR before trying to bind to its port?<br />

You can see the consequences <strong>of</strong> failing to set this option if you comment out that line and then try<br />

running the server. At first, you might think that it has no consequence. If all you are doing is stopping<br />

and starting the server, then you will see no effect at all:<br />

$ python tcp_sixteen.py server<br />

Listening at ('127.0.0.1', 1060)<br />

^C<br />

Traceback (most recent call last):<br />

...<br />

KeyboardInterrupt<br />

$ python tcp_sixteen.py server<br />

Listening at ('127.0.0.1', 1060)<br />

But you will see a big difference if you bring up the server, run the client against it, and then try<br />

killing and re-running the server. When the server starts back up, you will get an error:<br />

$ python tcp_sixteen.py server<br />

Traceback (most recent call last):<br />

...<br />

socket.error: [Errno 98] Address already in use<br />

How mysterious! Why would a bind() that can be repeated over and over again at one moment<br />

suddenly become impossible the next? If you keep trying to run the server without the SO_REUSEADDR<br />

option, you will find that the address does not become available again until several minutes after your<br />

last client connection!<br />

The answer is that, from the point <strong>of</strong> view <strong>of</strong> your operating system’s network stack, a socket that is<br />

merely listening can immediately be shut down and forgotten about, but a connected TCP socket—that is<br />

actually talking to a client—cannot immediately disappear when both ends have closed their connection<br />

and initiated the FIN handshakes in each direction. Why? Because after it sends the very last ACK packet,<br />

42

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!