def receive_data(sock, size):
"""Retrieve a given number of bytes from a socket.
It is expected the socket is able to supply that number of bytes.
If it isn't, an exception is raised (you will not get a zero length result
or a result that is smaller than what you asked for). The partial data that
has been received however is stored in the 'partialData' attribute of
the exception object."""
try:
delays = __retrydelays()
msglen = 0
data = bytearray()
if USE_MSG_WAITALL and not hasattr(sock, "getpeercert"): # ssl doesn't support recv flags
while True:
try:
chunk = sock.recv(size, socket.MSG_WAITALL)
if len(chunk) == size:
return chunk
# less data than asked, drop down into normal receive loop to finish
msglen = len(chunk)
data.extend(chunk)
break
except socket.timeout:
raise TimeoutError("receiving: timeout")
except socket.error as x:
err = getattr(x, "errno", x.args[0])
if err not in ERRNO_RETRIES:
raise ConnectionClosedError("receiving: connection lost: " + str(x))
time.sleep(next(delays)) # a slight delay to wait before retrying
# old fashioned recv loop, we gather chunks until the message is complete
while True:
try:
while msglen < size:
# 60k buffer limit avoids problems on certain OSes like VMS, Windows
chunk = sock.recv(min(60000, size - msglen))
if not chunk:
break
data.extend(chunk)
msglen += len(chunk)
if len(data) != size:
err = ConnectionClosedError("receiving: not enough data")
err.partialData = data # store the message that was received until now
raise err
return data # yay, complete
except socket.timeout:
raise TimeoutError("receiving: timeout")
except socket.error as x:
err = getattr(x, "errno", x.args[0])
if err not in ERRNO_RETRIES:
raise ConnectionClosedError("receiving: connection lost: " + str(x))
time.sleep(next(delays)) # a slight delay to wait before retrying
except socket.timeout:
raise TimeoutError("receiving: timeout")
评论列表
文章目录