Skip to main content

PodSixNet - lightweight multiplayer networking library for Python games

PodSixNet (now called podsixnet2) is a lightweight network layer designed to make it easy to write multiplayer games in Python. It uses Python’s built in asyncore library and rencode.py (included) to asynchronously serialise network events and arbitrary data structures, and deliver them to your high level classes through simple callback methods.

Each class within your game client which wants to receive network events, subclasses the ConnectionListener class and then implements Network_* methods to catch specific user-defined events from the server. You don’t have to wait for buffers to fill, or check sockets for waiting data or anything like that, just do connection.Pump() once per game loop and the library will handle everything else for you, passing off events to all classes that are listening. Sending data back to the server is just as easy, using connection.Send(mydata). Likewise on the server side, events are propagated to Network_* method callbacks and data is sent back to clients with the client.Send(mydata) method.

The podsixnet2 mailing list is good for getting help from other users.

For users of the Construct game making environment for Windows, there is a tutorial on doing multiplayer networking with podsixnet2, here. Thanks to Dave Chabo for contributing this tutorial.

Here is another tutorial by Julian Meyer.

Install

pip install podsixnet2

or

easy_install podsixnet2

From source

First make sure you have Python 2.4 or greater installed (python 3 also works).

Next you’ll want to get the podsixnet2 source.

The module is found inside a subdirectory called podsixnet2 within the top level folder. There’s an __init__.py inside there, so you can just copy or symlink the podsixnet2 sub-directory into your own project and then do import podsixnet2, or else you can run sudo python setup.py install to install podsixnet2 into your Python path. Use sudo python setup.py develop if you want to stay up to date with the cutting edge and still be able to svn/bzr up every now and then.

By default podsixnet2 uses a binary encoder to transfer data over the network, but it can optionally use the JSON format or other formats supported by a serialiser which has ‘dumps’ and ‘loads’ methods. If you want to serialise your data using JSON you can change the first line of Channel.py to ‘from simplejson import dumps, loads’ or use the built-in json library in Python 2.6 or higher. This will allow you to write game clients in languages that can’t read the ‘rencode’ binary format, such as Javascript.

Examples

Chat example:

  • python examples/ChatServer.py

  • and a couple of instances of python examples/ChatClient.py

Whiteboard example:

  • python examples/WhiteboardServer.py

  • and a couple of instances of python examples/WhiteboardClient.py

LagTime example (measures round-trip time from the server to the client):

  • python examples/LagTimeServer.py

  • and a couple of instances of python examples/LagTimeClient.py

Quick start - Server

You will need to subclass two classes in order to make your own server. Each time a client connects, a new Channel based class will be created, so you should subclass Channel to make your own server-representation-of-a-client class like this:

from podsixnet2.Channel import Channel

class ClientChannel(Channel):

    def Network(self, data):
        print data

    def Network_myaction(self, data):
        print "myaction:", data

Whenever the client does connection.Send(mydata), the Network() method will be called. The method Network_myaction() will only be called if your data has a key called ‘action’ with a value of “myaction”. In other words if it looks something like this:

data = {"action": "myaction", "blah": 123, ... }

Next you need to subclass the Server class like this:

from podsixnet2.Server import Server

class MyServer(Server):

    channelClass = ClientChannel

    def Connected(self, channel, addr):
        print 'new connection:', channel

Set channelClass to the channel class that you created above. The method Connected() will be called whenever a new client connects to your server. See the example servers for an idea of what you might do each time a client connects. You need to call Server.Pump() every now and then, probably once per game loop. For example:

myserver = MyServer()
while True:
    myserver.Pump()
    sleep(0.0001)

When you want to send data to a specific client/channel, use the Send method of the Channel class:

channel.Send({"action": "hello", "message": "hello client!"})

Quick start - Client

To have a client connect to your new server, you should use the Connection module. See pydoc Connection for more details, but here’s a summary:

Connection.connection is a singleton Channel which connects to the server. You’ll only have one of these in your game code, and you’ll use it to connect to the server and send messages to the server.

from podsixnet2.Connection import connection

# connect to the server - optionally pass hostname and port like: ("mccormick.cx", 31425)
connection.Connect()

connection.Send({"action": "myaction", "blah": 123, "things": [3, 4, 3, 4, 7]})

You’ll also need to put the following code once somewhere in your game loop:

connection.Pump()

Any time you have an object in your game which you want to receive messages from the server, subclass ConnectionListener. For example:

from podsixnet2.Connection import ConnectionListener

class MyNetworkListener(ConnectionListener):

    def Network(self, data):
        print 'network data:', data

    def Network_connected(self, data):
        print "connected to the server"

    def Network_error(self, data):
        print "error:", data['error'][1]

    def Network_disconnected(self, data):
        print "disconnected from the server"

    def Network_myaction(data):
        print "myaction:", data

Just like in the server case, the network events are received by Network_* callback methods, where you should replace ‘*’ with the value in the ‘action’ key you want to catch. You can implement as many or as few of the above as you like. For example, NetworkGUI would probably only want to listen for the _connected, _disconnected, and _error network events. The data for _error always comes in the form of network exceptions, like (111, ‘Connection refused’) - these are passed straight from the socket layer and are standard socket errors.

Another class might implement custom methods like Network_myaction(), which will receive any data that gets sent from the server with an ‘action’ key that has the name ‘myaction’. For example, the server might send a message with the number of players currently connected like so:

channel.Send({"action": "numplayers", "players": 10})

And the listener would look like this:

from podsixnet2.Connection import ConnectionListener

class MyPlayerListener(ConnectionListener):

    def Network_numplayers(data):
        # update gui element displaying the number of currently connected players
        print data['players']

You can subclass ConnectionListener as many times as you like in your application, and every class you make which subclasses it will receive the network events via named Network callbacks. You should call the Pump() method on each object you instantiate once per game loop:

gui = MyPlayerListener()
while 1:
    connection.Pump()
    gui.Pump()

License

Copyright Chris McCormick, 2009-2015.

podsixnet2 is licensed under the terms of the LGPL v3.0 or higher. See the file called COPYING for details.

This basically means that you can use it in most types of projects (commercial or otherwise), but if you make changes to the podsixnet2 code you must make the modified code available with the distribution of your software. Hopefully you’ll tell us about it so we can incorporate your changes. I am not a lawyer, so please read the license carefully to understand your rights with respect to this code.

Why not use Twisted instead?

Twisted is a fantastic library for writing robust network code. I have used it in several projects in the past, and it was quite nice to work with. That said, Twisted:

  • wants to steal the mainloop

  • is bloated not KISS (it implements many many different protocols)

  • has a weird template launching language when Python should do just fine

  • is not written 100% for the specfic use-case of multiplayer games

These are some of the reasons why I decided to write a library that is lightweight, has no dependencies except Python, and is dedicated 100% to the task of multiplayer game networking.

Metadata

Release files for podsixnet2 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for podsixnet2 2.0.1
File Size Uploaded Provenance Actions
podsixnet2-2.0.1.tar.gz 12.3 kB Without provenance Details for podsixnet2-2.0.1.tar.gz

Release files / podsixnet2-2.0.1.tar.gz

Download URL podsixnet2-2.0.1.tar.gz
Size 12.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f8382ab65e06e7fab5746b4ce7427e1ab7310298287cf92bf18a74a0b1a53852
BLAKE2b-256 checksum
How to use checksums
ed4bea69ac128b3812b4c78ac9fcb903efc5efcf9b528ffaa514ceb9e5f53cb7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.9.1 pkginfo/1.4.1 requests/2.18.4 setuptools/41.0.1 requests-toolbelt/0.8.0 tqdm/4.15.0 CPython/2.7.6

Security for podsixnet2 2.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

2.0.1 This release

1 release file No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page