Emitting event from client to server using python-socketio is extremely slow

167 views Asked by At

I'm using python-socketio for the first time, I have a simple AsyncServer that looks like this.

import socketio
from aiohttp import web

sio = socketio.AsyncServer()
app = web.Application()
sio.attach(app)

@sio.event
async def connect(sid, environ):
    print("Connected")

@sio.event
def set_name(sid, name):
    print("Set name: " + name)

if __name__ == "__main__":
    web.run_app(app)

And I have a client that looks like this.

import socketio

sio = socketio.AsyncClient()

async def start():
    await sio.connect("http://localhost:8080", transports=['websocket'])
    await sio.wait()

async def set_username(name):
    await sio.emit("set_name", name)

On the client, I use asyncio.run on the start function, and it connects successfully and instantly. However, later on when I do the same with the set_username function, it's EXTREMELY slow and takes a minute for the event to be recognized on the server-side.

I've tried using event loops in asyncio with no luck. I searched for similar problems on the Internet, found similar ones but none of their solutions worked for me.

1

There are 1 answers

4
IDobrodushniy On

Thanks for mentioning the versions of the libraries you have, this helped me to double check.

You mentioned you tried to run this code either with eventloop or asyncio.run and both had no success. The way you run your client is crucial here as the setup on the server is okay. You said at first you run connect and then you run set_username.

Not sure how exactly the set_username got triggered in your cases, but in the code you shared it simply isn't.

Please see the two scripts attached below as an example of how it could lok like and let me know if they work for you. What code does should be clear from the doc strings I hope.

# server.py

import socketio
from aiohttp import web

sio = socketio.AsyncServer()
app = web.Application()

sio.attach(app)


@sio.event
async def connect(sid, environ):
    """ Handle the connect event."""
    print(f"Sid {sid} connected.")


@sio.event
async def set_name(sid, name):
    """ Handle `set_name` event and sned a message back to the client that it was acknowledged."""
    print(f"Sid {sid} says: {name}.\nSending acknowledgment to {sid}.\n")
    await sio.emit("server-message", name, to=sid)


@sio.on("client_update")
async def handle_client_update(sid, value):
    """ Handle the `client_update` event and log the message."""
    print(f"Sid {sid} sends an update: {value}.\n")


if __name__ == "__main__":
    web.run_app(app)
# client.py

import asyncio
import random

import socketio

sio = socketio.AsyncClient()


async def main():
    """
    Connect to the server and then waits for events from it.
    """
    await sio.connect("ws://localhost:8080/", transports=['websocket'], )

    while True:
        await sio.emit("set_name", random.choice(("John", "Mike", "Bob")))
        await asyncio.sleep(1)


@sio.on("server-message")
async def get_from_server(name: str):
    """
    Get `server-message` event from server and print the log.
    """
    print(f"Server acknowledged that `{name}` was received.")


@sio.on("connect")
async def handle_connect_ack_from_server():
    """
    The handler will react to successful connection being established.
    """
    await sio.emit("client_update", "Thank you!")



if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main()) # you can replace me with `asyncio.run` - doesn't matter.

At first run the python3 server.py and then python3 client.py. After that you should see the logs both on the server and on the client:

  • Client sending set_name event every 1 second, so server will be logging it.
  • Server sending server-message to the client, so client will be logging it.

I hope this works