Online Game Give The Error "("connectionabortederror: [winerror 10053] "
Solution 1:
A quick read of the manual about socket.recv()
tells us that self.client.recv(4096)
uses that 4096 buf_size parameter as:
The maximum amount of data to be received at once is specified by [...]
So, it's the maximum, not the minimum. Your .recv()
will never receive more than 4096 bytes. That's all.
But the code is assuming it will always recv()
enough bytes:
return pickle.loads( self.client.recv(4096) ) # gambling a crash on Rx size
On your current network set-up, something is causing smaller packets to arrive at the recv()
, and not a full "pickle-worth". This is always an issue with network communications, it may be temporary, it may be permanent. Maybe a damp connection is causing packet loss, maybe maybe maybe. It was working before because the network/computers behaved differently.
So what do you do? The solution is check to see if any bytes have arrived. If bytes have arrived, add them to an "incoming-buffer". If there's enough bytes in the buffer, unpack it.
Pickling a data structure for sending over the network is probably an OK method, but I would first transmit the data-size of the pickled object, so the receiving client can know whether enough bytes have arrived to unpack it. Sure you can try..catch
the un-pickling, but that's grossly inefficient.
I would use struct.pack
to send the pickle-buffer size as a 4-byte integer (in network-byte order). Receive those 4 bytes first, then wait for the further N bytes to arrive.
EDIT: More details on struct, etc.
import struct
import pickle
defsendData( server_sock, object):
result = True
data = pickle.dumps( object )
data_size = struct.pack( '!I', len( data ) ) # good for 2^32 bytestry:
server_sock.sendall( data_size ) # send the size of the pickled obj
server_sock.sendall( data ) # send the objexcept:
sys.stderr.write( "Error sending data to server\n" )
result = Falsereturn result
And then to receive the data, read the 4-byte size field and then the pickle data. Something like the below should work (note: this is not tested code, I'm just answering off the top of my head)
defrecvData( client_sock ):
""" Try to receive a picked data-structure from the socket.
Returns True and an unpicked object, or False and None """
result = False
packet = None
expected = -1# First we read a 4-byte pickle size, and following that is /N/ bytes# of pickled structure data.# Read the 4-byte packet size first
buffer = bytes()
while ( len( buffer ) < 4 ):
try:
some_data = client_sock.recv( 4 - len( buffer ) )
if ( some_data ):
buffer.append( some_data )
if ( len( buffer ) == 4 ):
expected = struct.unpack( '!I', buffer )
except:
# TODO: work out which sort of exceptions are OKbreak# If we received a buffer size, try to receive the bufferif ( expected > 0 ):
buffer = bytes()
while ( len( buffer ) < expected ):
try:
some_data = client_sock.recv( expected - len( buffer ) )
if ( some_data ):
buffer.append( some_data )
# Have we received the full data-set yet?if ( len( buffer ) == expected ):
packet = pickle.loads( buffer )
result = True# successexcept:
# TODO: work out which sort of exceptions are OKbreakreturn result, packet
To be honest if you're just sending fixed amounts all the time (like a pair of x/y co-ordinates), it might be easier to just pack and unpack everything, using fixed-size datagrams. Maybe that's not "pythonic" enough though ;)
Anyway, what makes good network code is handling all the little rough edges. Sometimes (for a hundred different reasons), data does not arrive in nicely sized blocks, or your network blocks for a second or so. Simply handling this with a buffer, and non-blocking code solves 99% of the ills.
Really the recv()
above should be non-blocking code, but this is left as an exercise for the reader. I like to use select()
for this, but that's a bit old-fashioned.
Post a Comment for "Online Game Give The Error "("connectionabortederror: [winerror 10053] ""