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

[pygame] pygame networking redux



I've finally got some time to spend on building something useful for
pygame networking.

I've had a look at the latest Twisted (2.5), and it seems that there
is no longer any support for integrating the twisted event loop with
pygame. Bah.

Anyhow, I figure there is enough brains on this list for us to nut
something out, which is simple, and works on a variety of platforms.
So... if anyone is interested in helping out, please throw your 2c in.

I've attached my first thoughts in two .py files.

interface.py contains basic UDP class, and also contains classes
specific for each platform. (At this stage I'm not interested in
dealing with TCP connections)

pygnet.py contains a class for detecting missing packets in a
sequence, on a channel.

My idea is to build up layers of reliability using class inheritance,
so you can pick the class you need for the type of data you want to
send...

Once all this low-level stuff is done, we could add lobby systems,
score systems etc which are fairly generic and easily used across
different games/apps.

Anyone interested?




--
   :: Simon Wittber
   :: http://www.linkedin.com/in/simonwittber
   :: phone: +61.4.0135.0685
   :: jabber/msn: simonwittber@xxxxxxxxx
from socket import socket, AF_INET, SOCK_DGRAM, error
import sys


MAX_PACKET_SIZE = 1024

class BaseUDPInterface(object):
    def __init__(self, address):
        self.socket = socket(AF_INET, SOCK_DGRAM)
        self.socket.bind(address)
        self.socket.setblocking(0)
    
    def handle_error(self, e):
        pass

    def handle_recv(self, address, packet):
        pass

    def poll(self):
        try:
            packet, address = self.socket.recvfrom(MAX_PACKET_SIZE)
        except error, e:
            self.handle_error(e)
        else:
            self.handle_recv(address, packet)

    def send(self, address, packet):
        try:
            self.socket.sendto(packet, address)
        except error, e:
            self.handle_error(e)


if sys.platform[:5] == 'linux':
    class UDPInterface(BaseUDPInterface):
        def handle_error(self, e):
            pass 

elif sys.platform[:3] == 'win':
    class UDPInterface(BaseUDPInterface):
        def handle_error(self, e):
            pass 
import struct

from interface import UDPInterface

class UnreliableInterface(UDPInterface):
    def __init__(self, *args, **kw):
        UDPInterface.__init__(self, *args, **kw)
        self.outbound_channels = {}
        self.inbound_channels = {}

    def dispatch(self, channel, address, data):
        pass

    def send(self, address, channel, data):
        seq_id = self.outbound_channels.get(channel, 0)
        self.outbound_channels[channel] = seq_id + 1
        packet = struct.pack("!ii", channel, seq_id) + data
        UDPInterface.send(self, address, packet)

    def handle_missing(self, recieved_id, expected_id):
        pass

    def handle_recv(self, address, data):
        channel, seq_id = struct.unpack("!ii", data[:8])
        expected_seq_id = self.inbound_channels.get(channel, 0)
        if seq_id != expected_seq_id:
            self.handle_missing(seq_id, expected_seq_id)
        self.inbound_channels[channel] = seq_id + 1
        data = data[8:]
        self.dispatch(channel, address, data)


class ReliableInterface(UnreliableInterface):
    """
    This class needs to track sent packets, handle resend conditions etc.
    """
    pass


        
if __name__ == "__main__":
    s = UnreliableInterface(('127.0.0.1',1999))
    c = UnreliableInterface(('127.0.0.1',1992))
    for i in xrange(1000):
        s.send(('127.0.0.1',1992), 0, 'blah'*1000)
        s.poll()
        c.poll()