Foundations of Python Network Programming

(WallPaper) #1

Chapter 3 ■ tCp


44


Second, you will see that this TCP client is in one way much simpler than the UDP client, because it does not
need to make any provision for dropped packets. Because of the assurances that TCP provides, it can send() data
without even stopping to check whether the remote end receives it and run recv() without having to consider the
possibility of retransmitting its request. The client can rest assured that the network stack will perform any necessary
retransmission to get its data through.
Third, there is a direction in which this program is actually more complicated than the equivalent UDP code—
and this might surprise you because, with all of its guarantees, it sounds like TCP streams would be uniformly simpler
for the programmer than UDP datagrams. But precisely because TCP considers your outgoing and incoming data to
be, simply, streams with no beginning or end, it feels free to split them up into packets however it wants. And therefore
send() and recv() mean something different than they meant before. In the case of UDP, they simply meant, “send
this datagram” or “receive a datagram,” and each datagram was atomic: it either arrived or not as a self-contained
unit of data. An application will never see UDP datagrams that are only half-sent or half-received. Only fully intact
datagrams are ever delivered to a UDP application.
But TCP might split its data stream into packets of several different sizes during transmission and then gradually
reassemble them on the receiving end. Although this is vanishingly unlikely with the small 16-octet messages in
Listing 3-1, your code still needs to be prepared for the possibility. What are the consequences of TCP streaming for
both the send() and recv() calls?
Start by considering send(). When you perform a TCP send(), your operating system’s networking stack will face
one of three situations.


•    The data can be immediately accepted by the local system’s networking stack, either because
the network card is immediately free to transmit or because the system has room to copy the
data to a temporary outgoing buffer so that your program can continue running. In these
cases, send() returns immediately, and it will return the length of your data string as its return
value because the whole string is being transmitted.

•    Another possibility is that the network card is busy and that the outgoing data buffer for this
socket is full and the system cannot—or will not—allocate any more space. In this case, the
default behavior of send() is simply to block, pausing your program until the data can be
accepted for transmission.

•    There is a final, intermediate possibility: that the outgoing buffers are almost full, but not
quite, and so part of the data that you are trying to send can be immediately queued. But the
rest of the block of data will have to wait. In this case, send() completes immediately and
returns the number of bytes accepted from the beginning of your data string but leaves the rest
of the data unprocessed.

Because of this last possibility, you cannot simply call send() on a stream socket without checking the return
value. You have to put a send() call inside a loop that, in the case of a partial transmission, will keep trying to send the
remaining data until the entire byte string has been sent. You will sometimes see this expressed in networking code
using a loop like the following:


bytes_sent = 0
while bytes_sent < len(message):
message_remaining = message[bytes_sent:]
bytes_sent += s.send(message_remaining)


Fortunately, Python does not force you to do this dance yourself every time you have a block of data to send. As
a special convenience, the Standard Library socket implementation provides a friendly sendall() method(), which
Listing 3-1 uses instead. Not only is sendall() faster than doing it yourself, because it is implemented in C, but (for
those readers who know what this means) it releases the Global Interpreter Lock during its loop so that other Python
threads can run without contention until all of the data has been transmitted.

Free download pdf