Chapter 3 ■ tCp
46
$ python tcp_sixteen.py server ""
Listening at ('0.0.0.0', 1060)
Waiting to accept a new connection
We have accepted a connection from ('127.0.0.1', 57971)
Socket name: ('127.0.0.1', 1060)
Socket peer: ('127.0.0.1', 57971)
Incoming sixteen-octet message: b'Hi there, server'
Reply sent, socket closed
Waiting to accept a new connection
Having the client make one connection to the server, like this, produced the preceding output:
$ python3 tcp_sixteen.py client 127.0.0.1
Client has been assigned socket name ('127.0.0.1', 57971)
The server said b'Farewell, client'
You can see from the rest of the server code that once a connected socket has been returned by accept(), it works
exactly like a client socket with no further asymmetries evident in their pattern of communication. The recv() call
returns data as it becomes available, and sendall() is the best way to send a whole block of data when you want to
make sure it all gets transmitted.
You will note that an integer argument was provided to listen() when it was called on the server socket. This
number indicates how many waiting connections, which have not yet had sockets created for them by accept() calls,
should be allowed to stack up before the operating system starts ignoring new connections and deferring any further
three-way handshakes. I am using the very small value 1 here in the examples because I support only one example client
connecting at a time, but I will consider larger values for this call when I talk about network server design in Chapter 7.
Once the client and server have said everything that they need to, they close() their end of the socket which tells
the operating system to transmit any remaining data still left in their output buffer and then conclude the TCP session
with the FIN-packet shutdown procedure mentioned previously.
Address Already in Use
There is one last detail in Listing 3-1 about which you may be curious. Why is the server careful to set the socket
option SO_REUSEADDR before trying to bind to a port?
You can see the consequences of failing to set this option if you comment out that line and then try running the
server. At first, you might think that it has no consequence. If all you are doing is stopping and starting the server,
then you will see no effect at all (here I am starting the server and then terminating it with a simple Ctrl+C at the
terminal’s prompt):
$ python tcp_sixteen.py server ""
Listening at ('127.0.0.1', 1060)
Waiting to accept a new connection
^C
Traceback (most recent call last):
...
KeyboardInterrupt
$ python tcp_sixteen.py server ""
Listening at ('127.0.0.1', 1060)
Waiting to accept a new connection