Skip to content

Handling connections and disconnections

Server side

Override on_connect and on_disconnect on your Server subclass:

class GameServer(Server):
    channel_class = GameChannel

    def __init__(self, host: str = "127.0.0.1", port: int = 5071) -> None:
        super().__init__(host, port)
        self.players: list[GameChannel] = []

    def on_connect(self, channel: GameChannel, addr: tuple[str, int]) -> None:
        """Called when a new client connects."""
        print(f"New player from {addr}")
        self.players.append(channel)

    def on_disconnect(self, channel: GameChannel) -> None:
        """Called when a client disconnects."""
        print(f"Player left")
        if channel in self.players:
            self.players.remove(channel)

On the Channel, override on_connect and on_close:

class GameChannel(Channel):

    def on_connect(self) -> None:
        """Called when this channel's connection is established."""
        print(f"Client connected: {self.addr}")

    def on_close(self) -> None:
        """Called when this channel's connection is closed."""
        print(f"Client disconnected: {self.addr}")

Client side

On the client, these are just regular Network_* handlers:

class GameClient(ConnectionListener):

    def Network_connected(self, data: dict) -> None:
        print("Connected to server!")

    def Network_disconnected(self, data: dict) -> None:
        print("Lost connection.")

    def Network_error(self, data: dict) -> None:
        print(f"Connection error: {data.get('error')}")

Limiting connections

repod does not enforce a maximum number of connections at the transport level. Every TCP connection is accepted and handed a channel. This is intentional -- the "right" limit depends on your game: a pong match needs 2 players, a battle royale needs 100, and a chat room might have no cap at all.

Handle it in on_connect by checking your own count and rejecting the client with a message:

MAX_PLAYERS = 2


class GameServer(Server):
    channel_class = GameChannel

    def __init__(self, host: str = "127.0.0.1", port: int = 5071) -> None:
        super().__init__(host, port)
        self.players: list[GameChannel] = []

    def on_connect(self, channel: GameChannel, addr: tuple[str, int]) -> None:
        if len(self.players) >= MAX_PLAYERS:
            channel.send({"action": "full"})
            return

        self.players.append(channel)
        channel.send({"action": "welcome", "slot": len(self.players) - 1})

On the client side, handle the rejection:

class GameClient(ConnectionListener):

    def Network_full(self, data: dict) -> None:
        print("Server is full, try again later.")

This pattern gives you full control -- you can reject with a reason, put players in a spectator queue, or allow reconnection to an existing slot.