Skip to content

Instantly share code, notes, and snippets.

@kracekumar
Last active September 5, 2024 17:04
Show Gist options
  • Save kracekumar/daf10b3be3191a78b037c0c79667c26c to your computer and use it in GitHub Desktop.
Save kracekumar/daf10b3be3191a78b037c0c79667c26c to your computer and use it in GitHub Desktop.
Simple websocket server with uvloop.
# -*- coding: utf-8 -*-
import asyncio
import uvloop
from aiohttp.web import Application, MsgType, WebSocketResponse
def add_socket(app, socket, user_id):
if user_id in app['connections']:
pass
else:
print('New connection added {}'.format(user_id))
app['connections'][user_id] = socket
async def remove_socket(app, socket, user_id):
app['connections'].pop(user_id, None)
print('user id: {} is disconnected')
await socket.close()
async def ws_handler(request):
ws = WebSocketResponse()
await ws.prepare(request)
user_id = request.GET.get('user_id', -1)
async for msg in ws:
if msg.tp == MsgType.text:
if msg.data == 'close':
await remove_socket(app=ws.app, socket=ws, user_id=user_id)
else:
add_socket(app=request.app, socket=ws, user_id=user_id)
ws.send_str(msg.data * 2)
return ws
async def init(loop):
app = Application(loop=loop)
app['connections'] = {}
app.router.add_route('GET', '/', ws_handler)
handler = app.make_handler()
srv = await loop.create_server(handler, '127.0.0.1', '8000')
print("Server running on 127.0.0.1:8000")
return app, srv, handler
async def cleanup(app, srv, handler):
for idx, ws in app['connections'].items():
ws.close()
await asyncio.sleep(0.1)
srv.close()
await handler.finish_connections()
await srv.wait_closed()
def main():
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
app, srv, handler = loop.run_until_complete(init(loop))
try:
loop.run_forever()
except KeyboardInterrupt:
loop.run_until_complete(cleanup(app, srv, handler))
if __name__ == "__main__":
main()
@kracekumar
Copy link
Author

Sample benchmark

krace@Kracekumars-MacBook-Pro ~/D/PSSI> thor --amount 154 --messages 10 ws://localhost:8000

Thor:                                                  version: 1.0.0

God of Thunder, son of Odin and smasher of WebSockets!

Thou shall:
- Spawn 4 workers.
- Create all the concurrent/parallel connections.
- Smash 154 connections with the mighty Mjölnir.

The answers you seek shall be yours, once I claim what is mine.

Connecting to ws://localhost:8000

  Opened 100 connections


Online               554 milliseconds
Time taken           915 milliseconds
Connected            154
Disconnected         0
Failed               0
Total transferred    1.93MB
Total received       3.83MB

Durations (ms):

                     min     mean     stddev  median max
Handshaking          129     190          42     191 293
Latency              5       40           24      35 177

Percentile (ms):

                      50%     66%     75%     80%     90%     95%     98%     98%    100%
Handshaking          191     198     234     237     247     249     253     265     293
Latency              35      44      50      52      63      75      105     164     177

@mehmetkose
Copy link

it's realy clean ws example. Solid job.

@pyrossh
Copy link

pyrossh commented May 24, 2018

@solanu
Copy link

solanu commented Mar 14, 2019

Sample benchmark

Good job but it would be more useful if you compare the results with a uvloop-less version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment