Socket.sendall is very handy for sending. It would be nice if there was a socket.recvall. Unfortunatelty, receiving data is hard. One way to to do a recvall, is to use timeouts that get reset if any amount of data arrives. Useful, if you know almost nothing about what you are receiving.
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/213239
Another, if you can control the sender, is to use a sentinal or marker, and send when the end has arrived.
This example, shows a really simple way, to do that. The assumption is that you have a unique enough string as an end marker. You pass a socket to either of these functions. The sender takes on the end marker and the receiver looks for it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | End='something useable as an end marker'
def send_to_end(sock,data):
#assume the data is appendable, may need to stringify the data
sock.sendall(data+End)
def recvall2(the_socket):
#instead of doing
#data=the_socket.recv(8192)
#return data
total_data=[];data=''
while True:
#if recv returns 0 bytes, other side has closed
data=the_socket.recv(8192)
if End in data:
total_data.append(data[:data.find(End)])
break
total_data.append(data)
if len(total_data)>1:
#check if end_of_data was split
last_pair=total_data[-2]+total_data[-1]
if End in last_pair:
total_data[-2]=last_pair[:last_pair.find(End)]
total_data.pop()
break
result=''.join(total_data)
return result
|
I haven't seen any examples of a generic way to receive a lot of data by sending and looking for an end marker.
This way of doing is simple -- just put an end marker at the end of the data you are sending. If I get around to it, I'll change it to take account of the, hopefully very rare with a unique enough marker, situation where the data duplicates the end marker(oops).