ptrlib.connection.server

TCP/UDP server and connection abstractions.

This module provides: - Server: A TCP or UDP server class for managing incoming connections. - SocketClient: A Tube-based wrapper around an accepted client socket (TCP or UDP).

Features: - IPv4/IPv6, optional dualstack (IPv6 socket that accepts v4-mapped addresses on platforms that support it) - Thread-safe acceptance for TCP (multiple threads can call accept concurrently) - UDP acceptance: per-client connected UDP sockets on the same port using SO_REUSEPORT

Classes

SocketClient

A single accepted client connection (TCP or UDP) wrapped as a Tube.

Server

A TCP/UDP listening endpoint that accepts clients as SocketClient.

Module Contents

class ptrlib.connection.server.SocketClient(sock: socket.socket, peer: AddressT | None = None, **kwargs)[source]

Bases: ptrlib.connection.tube.Tube

A single accepted client connection (TCP or UDP) wrapped as a Tube.

This class is returned by Server.accept() and provides the usual buffered recv* / send* API backed by a connected socket.

Parameters:
  • sock – A connected socket (TCP/UDP). For TCP, a stream socket. For UDP, a datagram socket connected to a specific peer.

  • peer – Optional peer address tuple for display/logging.

Raises:

ValueError – If sock is not a connected TCP or UDP socket.

property remote_address: AddressT[source]

Return the peer (remote) address.

Raises:

RuntimeError – If the socket is closed.

property local_address: AddressT[source]

Return the local address.

Raises:

RuntimeError – If the socket is closed.

class ptrlib.connection.server.Server(host: str, port: int, *, backlog: int = 128, dualstack: bool = True, udp: bool = False)[source]

A TCP/UDP listening endpoint that accepts clients as SocketClient.

Thread-safe for concurrent accept() calls in TCP mode: multiple threads may call accept() simultaneously on the same instance and each will obtain distinct client connections (kernel arbiters which waiter gets awakened).

UDP mode:
  • The server binds a UDP socket.

  • Each accept() waits for one datagram to discover a peer, then creates a new per-client UDP socket bound to the same (addr, port) using SO_REUSEPORT (if available) and connects it to that peer. The initial datagram is pushed into the returned client’s buffer, so recv* sees it first.

Parameters:
  • host – Bind address (e.g., “0.0.0.0”, “::”, or hostname).

  • port – Port to listen on.

  • backlog – Listen backlog (TCP only).

  • dualstack – If True (TCP/UDP), prefer an IPv6 socket with IPV6_V6ONLY=0 to accept both IPv6 and IPv4 (platform-dependent).

  • udp – If True, run as a UDP server (default False -> TCP).

Raises:
  • OSError – Any OS-level failure during socket creation/bind/listen.

  • ValueError – Invalid arguments.

property fd: int[source]

Return the underlying listening FD.

Raises:

RuntimeError – If the server is closed.

property address: AddressT[source]

Return the bound (host, port[, flowinfo, scopeid]) address tuple.

Raises:

RuntimeError – If the server is closed.

close() None[source]

Close the listening socket.

Raises:

(never)

accept(timeout: float | int | None = None, **kwargs) SocketClient[source]

Accept a single incoming connection and wrap it as SocketClient.

TCP:
  • Blocks (with select) until a pending connection is ready, then returns a connected client.

UDP:
  • Waits for a datagram to arrive.

  • Creates a per-client UDP socket bound to the same port (SO_REUSEPORT) and connects it to the peer.

  • Pushes the first datagram into the client’s buffer so the next recv* call consumes it.

This method is safe to call concurrently from multiple threads in TCP mode. In UDP mode, concurrent calls are supported as long as SO_REUSEPORT is available.

Returns:

A Tube-like connection object for the accepted client.

Return type:

SocketClient

Raises:
  • TimeoutError – No connection (TCP) or datagram (UDP) arrived within timeout seconds.

  • OSError – Accept failed / socket errors.

  • RuntimeError – Server is closed.