The python3 socket programming howto presents this code snippet
class MySocket:
"""demonstration class only
- coded for clarity, not efficiency
"""
def __init__(self, sock=None):
if sock is None:
self.sock = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
else:
self.sock = sock
def connect(self, host, port):
self.sock.connect((host, port))
def mysend(self, msg):
totalsent = 0
while totalsent < MSGLEN:
sent = self.sock.send(msg[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent = totalsent + sent
def myreceive(self):
chunks = []
bytes_recd = 0
while bytes_recd < MSGLEN:
chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
if chunk == b'':
raise RuntimeError("socket connection broken")
chunks.append(chunk)
bytes_recd = bytes_recd + len(chunk)
return b''.join(chunks)
where the send loop is interrupted if the socket send
method returns 0.
The logic behind this snippet is that when the send
method returns '0 bytes sent', the sending side of a socket connection should give up its efforts to send data. This is for sure true for the recv
method, where zero bytes read for a socket in blocking mode should be interpreted as EOF
, and therefore the reading side should give up.
However I cannot understand under which situations the send
method could return zero. My understanding of python sockets is that send
returns immediately due to buffering at the OS level. If the buffer is full send
will block, or if the connections is closed at the remote side, an exception is raised.
Finally suppose send
returns zero without raising an exception: does this really indicate that all future send
calls will return zero?
I've done some testing (although using only socket connected to ::1
on OS X) and was not able to find a situation in which send
returns 0.
Edit
The HOWTO states:
But if you plan to reuse your socket for further transfers, you need to realize that there is no EOT on a socket. I repeat: if a socket send or recv returns after handling 0 bytes, the connection has been broken. If the connection has not been broken, you may wait on a recv forever, because the socket will not tell you that there’s nothing more to read (for now).
It is pretty easy to find a situation in which recv
returns 0: when the remote (sending) side calls socket.shutdown(SHUT_WR)
, further recv
on the receiving side will return 0
and not raise any exception.
I'm looking for a concrete example where you can show that receiving 0 zero from send
indicates a broken connection (which will continue to return 0 on send.)