[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] online game?



Kris Schnee schrieb:
...
> One question for others: I'm finding that even though I'm using the
> socket.select function to make sure a socket has data waiting, I can't
> seem to transmit large amounts of data (more than around 5 KB) without
> one side or the other hanging. (I'll have to look at the code more
> closely later to be more specific.) Any suggestions? My goal was to have
> a server part of my program run independently from both the player
> clients and a display client, but this bug seems to force me to develop
> some annoying protocol for things like sending a list of objects.
> "Prepare for N sending rounds on data for N objects..." rather than
> "here's the complete list of objects and their data all at once."
> 


Hi Kris,

Sending more than 5 KB works like a charm if you take care of the amount
of data you want to send:

   def _receive(self, MSGLEN):
      msg = ''
      while len(msg) < MSGLEN:
         chunk = self.sock.recv(MSGLEN-len(msg))
         if chunk == '':
            raise RuntimeError, \
                "socket connection broken: received " + str(len(msg)) +
" bytes " \
                + "but " + str(MSGLEN) + " bytes were expected"

         msg = msg + chunk
      return msg

the socket is initalized like this:
self.sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))

There is no information concerning the actual size inside the
default-socket-implementation.
Thus you have to add this information to your stream, here comes the
wrapping function:
   def receive(self):
      size = self._receive(7)
      recvsize = int(size.strip())
      message = self._receive(recvsize)
      return message

receive fetches the 6 byte long field with the message length (+1 byte
for a newline) at the front

Of course you need the corresponding sending functions:

   '''send inserts a 6 byte long field with the message length at the
front'''
   def send(self, msg):
      size = len(msg)
      if size > 999999:
         raise RuntimeError, "max messagesize is 999999 byte"
      sizefield = '{0:6}'.format(size)
      totalmessage = sizefield + "\n" + msg
      self._send(size + 7, totalmessage)
      print("pythonsocket: SEND " + repr(size) + " bytes")

def _send(self, MSGLEN, msg):
      totalsent = 0
      while totalsent < MSGLEN:
         sent = self.sock.send(msg[totalsent:])
         if sent == 0:
            raise RuntimeError, \
                "socket connection broken"
         totalsent = totalsent + sent

dont forget
      self.sock.close()
in the end.
(the code in this mail is ripped from a class containing a python socket
in self.sock
(import socket is necessary)

With this method data-interchange is only limited by a size of 999999
bytes, but this limit could be increased by an extended sizefield.


Cheers,
Enrico