Getting Started¶
Asyncio¶
Before trying this library you should understand the basics of python asyncio. You can read up on python 3 async basics here.
Creating the socket and server object¶
Before we can do anything you need to create the websocket object, we also create the eventloop.
loop = asyncio.get_event_loop()
socket = WebSocketServer(address, port, loop=loop)
Registering the on_connection callback¶
We can listen for new websocket connections with the connection()
decorator.
@socket.connection
async def on_connection(client: Client):
print("We just got a new connection!")
The parameter to the callback is the Client
class, more about that class later.
Starting the server¶
Before the server will accept connections we have to start it. Starting the server is as simple as using the
socket object as a context manager. The server
object yielded by the context manager is a Server
class.
with socket as server:
print(f'Serving on {server.sockets[0].getsockname()}')
print("The server closed")
The server closes as soon as the with block is done. In order to keep the server alive we need to give up control to the event loop.
We can do this with the run_forever()
method.
with socket as server:
loop.run_forever()
print("The server is going to close!")
print("The server closed")
The client object¶
If we look back at connection()
decorator, we see that the callback accepts the Server
class.
This class has 3 interesting attributes, addr
, port
, and writer
.
The first two answer to the address and port of the remote socket. We can use these to identify each client.
@socket.connection
async def on_connection(client: Client):
print(f"We just got a new connection from {client.addr, client.port}!")
The writer
is used to send messages to the client and we’ll look closer at it soon.
We can access all connected clients through clients
. This dict
the key to each client is the tuple (client.addr, client.port).
In particular before the on_connection callback is finished it contains all clients but the newly connected one.
@socket.connection
async def on_connection(client: Client):
for other in socket.clients.values():
print(f"Client {other.addr, other.port} was connected before {client.addr, client.port}")
Registering the on_message callback¶
In the same way we registered a on_connection callback we can register a on_message callback for a specific client, we usually do this at the same time as the client connect.
We do this with message()
decorator.
The callback parameter is a WebSocketReader
class.
@socket.connection
async def on_connection(client: Client):
@client.message
async def on_message(reader: WebSocketReader):
print(f"The client {client.addr, client.port} sent an message.")
Reading from the stream¶
The WebSocketReader
class inherits some low level read methods from it’s superclass Buffer
,
if you want to read bytes. Otherwise the method get()
is useful for reading either bytes
or str
.
@client.message
async def on_message(reader: WebSocketReader):
msg = await reader.get()
print(f"The client {client.addr, client.port} sent the message {msg}.")
Sending messages to the client¶
We can send messages to an client though the writer
attribute of type WebSocketWriter
Data frame¶
Just like we could receive messages with get()
we can send messages with send()
.
send()
will automatically look at the data you give it and send the correct data frame.
@socket.connection
async def on_connection(client: Client):
for other in socket.clients.values():
await other.writer.send('You are a client connected to my server.')
@socket.connection
async def on_connection(client: Client):
@client.message
async def on_message(reader: WebSocketReader):
msg = await reader.get()
await client.writer.send('You just send me the following message.')
await client.writer.send(msg)
Fragments¶
Coming soon
Other callbacks¶
Coming soon