ws
WebSocket implementation in Python built on top of websockets python library. Similar to Node.js's ws.
Basic usage.
server.py
import ws
server = ws.ServerSocket()
@server.on('ready')
async def on_ready():
print(f"Server is ready listening at ws://{server.address}:{server.port}")
@server.on('connect')
async def on_connect(client, path):
print(f"Client at {client.remote_address} connected.")
await client.send(
data={'status':"Okay", "alive": True, "ping": 10.4}
)
@server.on('message')
async def on_message(message):
print(f"{message.data}")
print(f"Received from: {message.author.remote_address} at {message.created_at}")
@server.on('disconnect')
async def on_disconnect(client, code, reason):
print(f"Client at {client.remote_address} disconnected with code: ", code, "and reason: ", reason)
print(server.disconnected_clients)
@server.on("close")
async def on_close(client, code, reason):
print(f"Client at {client.remote_address} closed connection with code: {code} and reason: {reason}")
server.listen("localhost", 3000)
client.py
import ws
client = ws.ClientSocket()
@client.on('connect')
async def on_connect():
print(f"Connected to {client.connection.remote_address}")
print(client.connection)
@client.on('message')
async def on_message(message):
print(f'{message.data}')
print(f'Status: {message.data.status} Alive: {message.data.alive} Ping: {message.data.ping}')
print(f"Received from: {message.author.remote_address} at {message.created_at}")
await message.author.send(content="Okay received.")
@client.on('disconnect')
async def on_disconnect(code, reason):
print(f"{client.connection} disconnect with code: ", code, "and reason: ", reason)
print(client.disconnection)
@client.on("close")
async def on_close(code, reason):
print(f"{client.connection.remote_address} closed connection with code: {code} and reason: {reason}")
client.connect("ws://localhost:3000")
Event collector (.wait_for method) example.
server.py
import ws
import asyncio
server = ws.ServerSocket()
@server.on('ready')
async def on_ready():
print(f"Server is ready listening at ws://{server.address}:{server.port}")
@server.on('connect')
async def on_connect(websocket, path):
print(f"Client at {websocket.remote_address} connected.")
@server.on('message')
async def on_message(message):
print(f"{message.data}")
if message.data.startswith("!confirm"):
await message.author.send("Send yes or no?")
try:
conmes = await server.wait_for(
'message',
timeout=300,
check=lambda rm: rm.data.lower().strip() in ['yes', 'no'] and rm.author.remote_address == message.author.remote_address)
print(conmes.data)
if conmes.data.lower().strip() == 'yes':
await conmes.author.send("done")
else:
await conmes.author.send("not done")
except asyncio.TimeoutError:
await message.author.send("Timed out!")
@server.on('disconnect')
async def on_disconnect(client, code, reason):
print(f"{client} disconnect with code:", code, reason)
print(server.disconnected_clients)
@server.on("close")
async def on_close(client, code, reason):
print(f"{client.remote_address} closed connection with code: {code} and reason: {reason}")
server.listen("localhost", 3000)
client.py
import ws
import asyncio
client = ws.ClientSocket()
@client.on('connect')
async def on_connect():
print(f"Connected to {client.connection.remote_address}")
await client.send(content="!confirm")
@client.on('message')
async def on_message(message):
print(f'{message.data}')
if message.data in ['done', 'not done']:
return
await asyncio.sleep(3)
await message.author.send(
"This is a random message. This won't be collected by the event collector on the server side due to the check condition."
)
await asyncio.sleep(3)
await message.author.send(
"yes"
) #this will be collected and you would receive a response "done" for this, provide "no" and you will get "not done" response
@client.on('disconnect')
async def on_disconnect(code, reason):
print(f"{client.connection} disconnect with code:", code, reason)
print(client.disconnection)
@client.on("close")
async def on_close(code, reason):
print(f"{client.connection.remote_address} closed connection with code: {code} and reason: {reason}")
client.connect("ws://localhost:3000")
FAQ
on_disconnect
and on_close
event listeners ?
What's the difference between The difference isn't huge but it is there. on_disconnect
event is fired only if the client or the server did not closed the connection properly, the TCP Connection was lost suddenly raising the websockets' ConnectionClosedError in the libraries internal message consumer. In such cases the code returned is usually 1006
and there is no reason. While on_close
event listener is called if the connection was closed properly, that could be done by calling the libraries' ClientSocket or ServerSocket's .close
method and providing a reason and error code optionally. This causes the internal message consumer task on both sides to exit / return that in turn calls the attached listener functions. Note: Unlike on_disconnect
listener, on_close
is called on both sides that is both on the client and server websocket sides with the same reason and code.
Why this exists?
I made this library because I was fed up of websockets library because it didn't have event based communication like Node.js's ws library and that made it difficult to work about it. Before I was doubtful whether I would work on it anymore or not... but it has went on to become a pretty large library but still not well known as of now...