select.select and socket.setblocking

Karen Tracey kmtracey at gmail.com
Wed Dec 31 16:21:48 CET 2008


On Wed, Dec 31, 2008 at 5:39 AM, Francesco Bochicchio
<bockman at virgilio.it>wrote:

> Francesco Bochicchio ha scritto:
>
>>
>>> No, in blocking mode it will wait to receive _some_ data (1 or
>>> more bytes).  The "requested" amount is strictly an upper
>>> limit: recv won't return more than the requested number of
>>> bytes, but it might return less.
>>>
>>>
>> Uhm. In my experience, with TCP protocol recv only returned less than the
>> required bytes if the remote end disconnects. I always check the
>> returned value of recv and signal an error if the read bytes are less than
>> the expected ones, but this error is never occurred (and its about 20 years
>> that I use sockets in various languages and various flavor of unix and
>> occasionally on windows. Maybe  have always been lucky ? :-)
>>
>>
> BTW, this is not a rethorical or ironic question... my applications mostly
> run on LANs or dedicated WANs so maybe they never experienced the
> kind of network congestion that could cause recv to return less than the
> expected amount of bytes ...
>
> but then, IIRC TCP guarantees that the packet is fully received by
> hand-shaking at transport level between sender and receiver. Ad once the
> packet is fully in the receiver buffer, why should recv choose to give
> back to the application only a piece of it?
>

One way to get less data than you ask for: TCP internally buffers a finite
amount of data for your connection.  If you ever ask to receive in one
recv() call more than TCP is willing to buffer for your connection, you will
get back only what TCP has buffered, not the amount you ask for, even if the
other side has sent the larger amount.  The remaining data will likely be
buffered in the TCP send buffers on the other side of the connection*.  Your
call to recv() will empty your side's receive buffers (it is likely TCP will
return all the data it has buffered in a single call, though I don't think
that is an API requirement), causing your side's TCP to send a window update
to the other side indicating it is willing to receive more data on the
connection, the data will be transfered, and a subsequent recv() call by
your application will be able to retrieve more of the data.

TCP provides a stream of bytes to its applications, not a datagram/packet
interface.  Assuming "packets" sent by one side will be received in their
entirety on a single receive call on the other side is really asking for
trouble.  TCP does not maintain any sort of packet boundaries that you seem
to think are implied by the sequence of sends issued on one side of the
connection.

Karen

*This is assuming the other side's send buffers aren't filled up by the
left-over data your TCP isn't willing to buffer.  If they are, and the
sending socket is in blocking mode, the sender will have been blocked during
the send waiting for buffer space to free up.  If the sender's socket is
non-blocking, and both the send and receive buffers fill up, then the
sending socket will start returning EWOULDBLOCK or EAGAIN (I forget which)
on calls to send data, until some buffer space is freed up by your side's
receiving some data.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20081231/f52702f8/attachment.html>


More information about the Python-list mailing list