Servers API
Network server module.
Abstract Base Classes
Network server interfaces definition module.
- class easynetwork.servers.abc.AbstractAsyncNetworkServer
Bases:
objectThe base class for an asynchronous network server.
- async __aenter__() Self
Calls
server_activate().- Return type:
- async __aexit__(exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None) None
Calls
server_close().
- abstract is_serving() bool
Checks whether the server is up (
is_listening()returnsTrue) and accepting new clients.- Return type:
- abstract async serve_forever(*, is_up_event: SupportsEventSet | None = ...) None
Starts the server’s main loop.
Further calls to
is_serving()will returnTrueuntil the loop is stopped.- Parameters:
is_up_event (SupportsEventSet | None) – If given, will be triggered when the server is ready to accept new clients.
- Raises:
ServerClosedError – The server is closed.
ServerAlreadyRunning – Another task already called
serve_forever().
- abstract async server_activate() None
Opens all listeners.
This method MUST be idempotent. Further calls to
is_listening()will returnTrue.- Raises:
ServerClosedError – The server is closed.
- abstract async shutdown() None
Asks for the server to stop.
All active client tasks will be cancelled.
Warning
Do not call this method in the
serve_forever()task; it will cause a deadlock.
- abstract backend() AsyncBackend
- Returns:
The backend implementation linked to this server.
- Return type:
- class easynetwork.servers.abc.AbstractNetworkServer
Bases:
objectThe base class for a network server.
- abstract is_serving() bool
Checks whether the server is up and accepting new clients. Thread-safe.
- Return type:
- abstract serve_forever(*, is_up_event: SupportsEventSet | None = ...) None
Starts the server’s main loop.
- Parameters:
is_up_event (SupportsEventSet | None) – If given, will be triggered when the server is ready to accept new clients.
- Raises:
ServerClosedError – The server is closed.
ServerAlreadyRunning – Another task already called
serve_forever().
- abstract shutdown(timeout: float | None = ...) None
Asks for the server to stop. Thread-safe.
All active client tasks will be cancelled.
Warning
Do not call this method in the
serve_forever()thread; it will cause a deadlock.- Parameters:
timeout (float | None) – The maximum amount of seconds to wait.
- protocol easynetwork.servers.abc.SupportsEventSet
Bases:
ProtocolA
threading.Event-like object.Classes that implement this protocol must have the following methods / attributes:
Asynchronous Server Objects (async def)
TCP Implementation
Asynchronous TCP Network server implementation module.
- class easynetwork.servers.async_tcp.AsyncTCPNetworkServer
Bases:
AbstractAsyncNetworkServer,Generic[_T_Request,_T_Response]An asynchronous network server for TCP connections.
- __init__(host: str | None | Sequence[str], port: int, protocol: AnyStreamProtocolType[_T_Response, _T_Request], request_handler: AsyncStreamRequestHandler[_T_Request, _T_Response], backend: AsyncBackend | BuiltinAsyncBackendLiteral | None = None, *, ssl: SSLContext | None = None, ssl_handshake_timeout: float | None = None, ssl_shutdown_timeout: float | None = None, ssl_standard_compatible: bool | None = None, backlog: int | None = None, reuse_port: bool = False, max_recv_size: int | None = None, log_client_connection: bool | None = None, logger: logging.Logger | None = None) None
- Parameters:
host (str | None | Sequence[str]) –
Can be set to several types which determine where the server would be listening:
If host is a string, the TCP server is bound to a single network interface specified by host.
If host is a sequence of strings, the TCP server is bound to all network interfaces specified by the sequence.
If host is
None, all interfaces are assumed and a list of multiple sockets will be returned (most likely one for IPv4 and another one for IPv6).
port (int) – specify which port the server should listen on. If the value is
0, a random unused port will be selected (note that if host resolves to multiple network interfaces, a different random port will be selected for each interface).protocol (AnyStreamProtocolType[_T_Response, _T_Request]) – The protocol object to use.
request_handler (AsyncStreamRequestHandler[_T_Request, _T_Response]) – The request handler to use.
backend (AsyncBackend | BuiltinAsyncBackendLiteral | None) – The asynchronous backend interface to use.
- Keyword Arguments:
ssl – can be set to an
ssl.SSLContextinstance to enable TLS over the accepted connections.ssl_handshake_timeout – (for a TLS connection) the time in seconds to wait for the TLS handshake to complete before aborting the connection.
60.0seconds ifNone(default).ssl_shutdown_timeout – the time in seconds to wait for the SSL shutdown to complete before aborting the connection.
30.0seconds ifNone(default).ssl_standard_compatible – if
False, skip the closing handshake when closing the connection, and don’t raise an exception if the peer does the same.backlog – is the maximum number of queued connections passed to
listen(defaults to100).reuse_port – tells the kernel to allow this endpoint to be bound to the same port as other existing endpoints are bound to, so long as they all set this flag when being created. This option is not supported on Windows.
max_recv_size – Read buffer size. If not given, a default reasonable value is used.
log_client_connection – If
True, log clients connection/disconnection inlogging.INFOlevel. (This log will always be available inlogging.DEBUGlevel.)logger – If given, the logger instance to use.
See also
- get_addresses() Sequence[IPv4SocketAddress | IPv6SocketAddress]
Returns all interfaces to which the server is bound.
- Returns:
A sequence of network socket address. If the server is not serving (
is_serving()returnsFalse), an empty sequence is returned.- Return type:
- get_sockets() Sequence[SocketProxy]
Gets the listeners sockets.
- Returns:
a read-only sequence of
SocketProxyobjects.If the server is not running, an empty sequence is returned.
- Return type:
- backend() AsyncBackend
- Returns:
The backend implementation linked to this server.
- Return type:
- is_serving() bool
Checks whether the server is up (
is_listening()returnsTrue) and accepting new clients.- Return type:
- async serve_forever(*, is_up_event: SupportsEventSet | None = None) None
Starts the server’s main loop.
Further calls to
is_serving()will returnTrueuntil the loop is stopped.- Parameters:
is_up_event (SupportsEventSet | None) – If given, will be triggered when the server is ready to accept new clients.
- Raises:
ServerClosedError – The server is closed.
ServerAlreadyRunning – Another task already called
serve_forever().
- async server_activate() None
Opens all listeners.
This method MUST be idempotent. Further calls to
is_listening()will returnTrue.- Raises:
ServerClosedError – The server is closed.
- async shutdown() None
Asks for the server to stop.
All active client tasks will be cancelled.
Warning
Do not call this method in the
serve_forever()task; it will cause a deadlock.
UDP Implementation
Asynchronous UDP Network client implementation module.
- class easynetwork.servers.async_udp.AsyncUDPNetworkServer
Bases:
AbstractAsyncNetworkServer,Generic[_T_Request,_T_Response]An asynchronous network server for UDP communication.
- __init__(host: str | None | Sequence[str], port: int, protocol: DatagramProtocol[_T_Response, _T_Request], request_handler: AsyncDatagramRequestHandler[_T_Request, _T_Response], backend: AsyncBackend | Literal['asyncio', 'trio'] | None = None, *, reuse_port: bool = False, logger: Logger | None = None) None
- Parameters:
host (str | None | Sequence[str]) – specify which network interface to which the server should bind.
port (int) – specify which port the server should listen on. If the value is
0, a random unused port will be selected (note that if host resolves to multiple network interfaces, a different random port will be selected for each interface).protocol (DatagramProtocol[_T_Response, _T_Request]) – The protocol object to use.
request_handler (AsyncDatagramRequestHandler[_T_Request, _T_Response]) – The request handler to use.
backend (AsyncBackend | Literal['asyncio', 'trio'] | None) – The asynchronous backend interface to use.
- Keyword Arguments:
reuse_port – tells the kernel to allow this endpoint to be bound to the same port as other existing endpoints are bound to, so long as they all set this flag when being created. This option is not supported on Windows.
logger – If given, the logger instance to use.
- get_addresses() Sequence[IPv4SocketAddress | IPv6SocketAddress]
Returns all interfaces to which the server is bound.
- Returns:
A sequence of network socket address. If the server is not serving (
is_serving()returnsFalse), an empty sequence is returned.- Return type:
- get_sockets() Sequence[SocketProxy]
Gets the listeners sockets.
- Returns:
a read-only sequence of
SocketProxyobjects.If the server is not running, an empty sequence is returned.
- Return type:
- backend() AsyncBackend
- Returns:
The backend implementation linked to this server.
- Return type:
- is_serving() bool
Checks whether the server is up (
is_listening()returnsTrue) and accepting new clients.- Return type:
- async serve_forever(*, is_up_event: SupportsEventSet | None = None) None
Starts the server’s main loop.
Further calls to
is_serving()will returnTrueuntil the loop is stopped.- Parameters:
is_up_event (SupportsEventSet | None) – If given, will be triggered when the server is ready to accept new clients.
- Raises:
ServerClosedError – The server is closed.
ServerAlreadyRunning – Another task already called
serve_forever().
- async server_activate() None
Opens all listeners.
This method MUST be idempotent. Further calls to
is_listening()will returnTrue.- Raises:
ServerClosedError – The server is closed.
- async shutdown() None
Asks for the server to stop.
All active client tasks will be cancelled.
Warning
Do not call this method in the
serve_forever()task; it will cause a deadlock.
Synchronous Server Objects
TCP Implementation
TCP Network server implementation module.
- class easynetwork.servers.standalone_tcp.StandaloneTCPNetworkServer
Bases:
AbstractNetworkServer,Generic[_T_Request,_T_Response]A network server for TCP connections.
It embeds an
AsyncTCPNetworkServerinstance.- __init__(host: str | None | Sequence[str], port: int, protocol: AnyStreamProtocolType[_T_Response, _T_Request], request_handler: AsyncStreamRequestHandler[_T_Request, _T_Response], backend: AsyncBackend | BuiltinAsyncBackendLiteral | None = None, *, runner_options: Mapping[str, Any] | None = None, ssl: _SSLContext | None = None, ssl_handshake_timeout: float | None = None, ssl_shutdown_timeout: float | None = None, ssl_standard_compatible: bool | None = None, backlog: int | None = None, reuse_port: bool = False, max_recv_size: int | None = None, log_client_connection: bool | None = None, logger: logging.Logger | None = None, **kwargs: Any) None
For the other arguments, see
AsyncTCPNetworkServerdocumentation.- Parameters:
backend (AsyncBackend | BuiltinAsyncBackendLiteral | None) – The asynchronous backend interface to use. It defaults to
asyncioimplementation.runner_options (Mapping[str, Any] | None) – Options to pass to the
AsyncBackend.bootstrap()method.
- get_addresses() Sequence[IPv4SocketAddress | IPv6SocketAddress]
Returns all interfaces to which the server is bound. Thread-safe.
- Returns:
A sequence of network socket address. If the server is not serving (
is_serving()returnsFalse), an empty sequence is returned.- Return type:
- get_sockets() Sequence[SocketProxy]
Gets the listeners sockets. Thread-safe.
- Returns:
a read-only sequence of
SocketProxyobjects.If the server is not running, an empty sequence is returned.
- Return type:
- is_serving() bool
Checks whether the server is up and accepting new clients. Thread-safe.
- Return type:
- serve_forever(*, is_up_event: SupportsEventSet | None = None, runner_options: Mapping[str, Any] | None = None) None
Starts the server’s main loop.
- Parameters:
is_up_event (SupportsEventSet | None) – If given, will be triggered when the server is ready to accept new clients.
runner_options (Mapping[str, Any] | None) – Options to pass to the
AsyncBackend.bootstrap()method. The specified keys override the keys passed at initialization.
- Raises:
ServerClosedError – The server is closed.
ServerAlreadyRunning – Another task already called
serve_forever().
UDP Implementation
UDP Network client implementation module.
- class easynetwork.servers.standalone_udp.StandaloneUDPNetworkServer
Bases:
AbstractNetworkServer,Generic[_T_Request,_T_Response]A network server for UDP communication.
It embeds an
AsyncUDPNetworkServerinstance.- __init__(host: str | None | Sequence[str], port: int, protocol: DatagramProtocol[_T_Response, _T_Request], request_handler: AsyncDatagramRequestHandler[_T_Request, _T_Response], backend: AsyncBackend | Literal['asyncio', 'trio'] | None = None, *, runner_options: Mapping[str, Any] | None = None, reuse_port: bool = False, logger: Logger | None = None, **kwargs: Any) None
For the other arguments, see
AsyncUDPNetworkServerdocumentation.- Parameters:
backend (AsyncBackend | Literal['asyncio', 'trio'] | None) – The asynchronous backend interface to use. It defaults to
asyncioimplementation.runner_options (Mapping[str, Any] | None) – Options to pass to the
AsyncBackend.bootstrap()method.
- get_addresses() Sequence[IPv4SocketAddress | IPv6SocketAddress]
Returns all interfaces to which the server is bound. Thread-safe.
- Returns:
A sequence of network socket address. If the server is not serving (
is_serving()returnsFalse), an empty sequence is returned.- Return type:
- get_sockets() Sequence[SocketProxy]
Gets the listeners sockets. Thread-safe.
- Returns:
a read-only sequence of
SocketProxyobjects.If the server is not running, an empty sequence is returned.
- Return type:
- is_serving() bool
Checks whether the server is up and accepting new clients. Thread-safe.
- Return type:
- serve_forever(*, is_up_event: SupportsEventSet | None = None, runner_options: Mapping[str, Any] | None = None) None
Starts the server’s main loop.
- Parameters:
is_up_event (SupportsEventSet | None) – If given, will be triggered when the server is ready to accept new clients.
runner_options (Mapping[str, Any] | None) – Options to pass to the
AsyncBackend.bootstrap()method. The specified keys override the keys passed at initialization.
- Raises:
ServerClosedError – The server is closed.
ServerAlreadyRunning – Another task already called
serve_forever().
Request Handler Interface
Asynchronous network servers’ request handler base classes module.
- class easynetwork.servers.handlers.AsyncStreamRequestHandler
Bases:
Generic[_T_Request,_T_Response]The base class for a stream request handler, used by TCP network servers.
- async service_init(exit_stack: AsyncExitStack, server: Any, /) None
Called at server startup. The default implementation does nothing.
- Parameters:
exit_stack (AsyncExitStack) – An
AsyncExitStackthat can be used to add actions on server’s tear down.server (Any) – A
weakref.proxy()to the server instance.
- abstract handle(client: AsyncStreamClient[_T_Response], /) AsyncGenerator[float | None, _T_Request]
This function must do all the work required to service a request.
It is an asynchronous generator function:
async def handle(self, client): request = yield # Do some stuff ... await client.send_packet(response)
handle()canyieldwhenever a request from the client is needed.The generator is started immediately after
on_connection(). When the generator returns, a new generator is created and started immediately after.The generator does not represent the client life time,
await client.aclose()must be called explicitly.Note
There is one exception: if the generator returns before the first
yieldstatement, the connection is forcibly closed.- Parameters:
client (AsyncStreamClient[_T_Response]) – An interface to communicate with the remote endpoint.
- Yields:
Noneor a number interpreted as the timeout delay.- Return type:
AsyncGenerator[float | None, _T_Request]
- on_connection(client: AsyncStreamClient[_T_Response], /) Coroutine[Any, Any, None] | AsyncGenerator[float | None, _T_Request]
Called once the client is connected to perform any initialization actions required. The default implementation does nothing.
It can be either a coroutine function:
async def on_connection(self, client): # Do some stuff ...
or an asynchronous generator function:
async def on_connection(self, client): # Do some stuff ... initial_info = yield # Finish initialization ...
In the latter case, as for
handle(),on_connection()canyieldwhenever a request from the client is needed.- Parameters:
client (AsyncStreamClient[_T_Response]) – An interface to communicate with the remote endpoint.
- Yields:
If it is an asynchronous generator,
Noneor a number interpreted as the timeout delay.- Return type:
Coroutine[Any, Any, None] | AsyncGenerator[float | None, _T_Request]
- async on_disconnection(client: AsyncStreamClient[_T_Response], /) None
Called once the client is disconnected to perform any clean-up actions required. The default implementation does nothing.
This function will not be called in the following conditions:
If
on_connection()raises an exception.If
on_connection()is an asynchronous generator function and the connection is closed.
Important
AsyncStreamClient.is_closing()should returnTruewhen this function is called. However, ifhandle()raises an exception, the client task is shut down and the connection is forcibly closed afteron_disconnection()is called.This behavior allows you to notify the client that something unusual has occurred.
- Parameters:
client (AsyncStreamClient[_T_Response]) – An interface to communicate with the remote endpoint.
- class easynetwork.servers.handlers.AsyncDatagramRequestHandler
Bases:
Generic[_T_Request,_T_Response]The base class for a datagram request handler, used by UDP network servers.
- async service_init(exit_stack: AsyncExitStack, server: Any, /) None
Called at server startup. The default implementation does nothing.
- Parameters:
exit_stack (AsyncExitStack) – An
AsyncExitStackthat can be used to add actions on server’s tear down.server (Any) – A
weakref.proxy()to the server instance.
- abstract handle(client: AsyncDatagramClient[_T_Response], /) AsyncGenerator[float | None, _T_Request]
This function must do all the work required to service a request.
It is an asynchronous generator function:
async def handle(self, client): request = yield # Do some stuff ... await client.send_packet(response)
handle()canyieldwhenever a request from the client is needed.Warning
UDP does not guarantee ordered delivery. Packets are typically “sent” in order, but they may be received out of order. In large networks, it is reasonably common for some packets to arrive out of sequence (or not at all).
Since there is no connection management, the generator is started when the datagram is received. When the generator returns, a new generator is created and started when a new datagram is received.
Important
There will always be only one active generator per client. All the pending datagrams received while the generator is running are queued.
This behavior is designed to act like a stream request handler.
Note
If the generator returns before the first
yieldstatement, the received datagram is discarded.This is useful when a client that you do not expect to see sends something; the datagrams are parsed only when the generator hits a
yieldstatement.- Parameters:
client (AsyncDatagramClient[_T_Response]) – An interface to communicate with the remote endpoint.
- Yields:
Noneor a number interpreted as the timeout delay.- Return type:
AsyncGenerator[float | None, _T_Request]
Client API
- class easynetwork.servers.handlers.AsyncBaseClientInterface
Bases:
TypedAttributeProvider,Generic[_T_Response]The base class for a client interface, used by request handlers.
- abstract async send_packet(packet: _T_Response, /) None
Sends packet to the remote endpoint. Does not require task synchronization.
Warning
In the case of a cancellation, it is impossible to know if all the packet data has been sent. This would leave the connection in an inconsistent state.
- Parameters:
packet (_T_Response) – the Python object to send.
- Raises:
ClientClosedError – the client object is closed.
ConnectionError – connection unexpectedly closed during operation. You should not attempt any further operation and close the client object.
OSError – unrelated OS error occurred. You should check
OSError.errno.
- abstract is_closing() bool
Checks if the client is closed or in the process of being closed.
If
True, all future operations on the client object will raise aClientClosedError.- Returns:
the client state.
- Return type:
- abstract backend() AsyncBackend
- Returns:
The backend implementation linked to the server.
- Return type:
- class easynetwork.servers.handlers.AsyncStreamClient
Bases:
AsyncBaseClientInterface[_T_Response]A client interface for stream oriented connection, used by stream request handlers.
- abstract async aclose() None
Close the client. Does not require task synchronization.
Once that happens, all future operations on the client object will raise a
ClientClosedError. The remote end will receive no more data (after queued data is flushed).Can be safely called multiple times.
Warning
aclose()performs a graceful close, waiting for the connection to close.If
aclose()is cancelled, the client is closed abruptly.
- class easynetwork.servers.handlers.AsyncDatagramClient
Bases:
AsyncBaseClientInterface[_T_Response]A client interface for datagram oriented connection, used by datagram request handlers.
Unlike
AsyncStreamClient, the client object can be recreated on eachhandle()call, but implements__hash__()and__eq__()for uniqueness checking, so it can be used in asetfor example.
Server implementation tools
See also
- How-to — TCP Servers and How-to — UDP Servers
Describes what can be done with the servers.
- How-to — Standalone Servers
Explains the case of stand-alone servers.