Search code examples
python-3.xflaskflask-socketiopython-socketio

Flask-socketio doesn't recieve message from client


I'm trying to write a basic Socket.io program where the python client (python-socketio[asyncio_client] 4.6.0) emits a single string message to the flask server (with Flask-SocketIO 4.3.1 and eventlet).

The client appears to connect and send the message properly, but there is no output seen at the Flask server.

Server code:

from flask import Flask
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

@socketio.on('connect')
def test_connect():
    print('connected')


@socketio.on('disconnect')
def test_disconnect():
    print('Client disconnected')

@socketio.on('message')
def handle_message(msg):
    print('Recieved',msg)

@socketio.on('json')
def handle_json(json):
    print(str(json))

if __name__ == '__main__':
    socketio.run(app,debug=True)

Client code:

    import asyncio
    import socketio
    
    sio = socketio.AsyncClient()
    
    @sio.event
    def connect():
        print('connection established')
    
    @sio.event
    def disconnect():
        print('disconnected from server')
    
    async def main():
        await sio.connect('http://localhost:5000')
        await sio.emit('message',data='detection')
        print('message sent')
        await sio.disconnect()
    
    if __name__ == '__main__':
        asyncio.run(main())

Server output:

PS C:\Users\daksh\sih\sihPython> python .\test_socketio.py
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 101-561-255
(16664) wsgi starting up on http://127.0.0.1:5000
(16664) accepted ('127.0.0.1', 59497)
connected
127.0.0.1 - - [23/Jul/2020 20:38:42] "GET /socket.io/?transport=polling&EIO=3&t=1595516920.71801 HTTP/1.1" 200 367 0.004934
Client disconnected
127.0.0.1 - - [23/Jul/2020 20:38:42] "GET /socket.io/?transport=websocket&EIO=3&sid=88790300120f4b899e019ae7cc16ee87&t=1595516922.7757218 HTTP/1.1" 200 0 0.010027

Client output:

PS C:\Users\daksh\sih\sihPython> python .\socketio-client.py
connection established
message sent

The print statement from handle_message() is missing in the server output.

I've gone through multiple tutorials online, and I've tried it with and without namespaces. Have not been able to figure out what's wrong.

Any help is appreciated.

(I'm using Python 3.8.3 on Windows 10)

UPDATE: It works if I change the client code to use socketio.Client() instead of AsyncClient(), however I need the client to connect using AsyncClient.


Solution

  • The problem is that your async client is obviously asynchronous, you can't just send and exit because you don't give the background tasks that support the Socket.IO protocol time to do their thing.

    Here is a more robust version of the client that lets the event go through before exiting:

    import asyncio
    import socketio
    
    sio = socketio.AsyncClient()
    
    @sio.event
    async def connect():
        print('connection established')
        await sio.emit('message',data='detection', callback=done)
        print('message sent')
    
    @sio.event
    def disconnect():
        print('disconnected from server')
    
    async def done():
        await sio.disconnect()
    
    async def main():
        await sio.connect('http://localhost:5000')
        await sio.wait()
    
    if __name__ == '__main__':
        asyncio.run(main())
    

    The trick here is to use a callback on the emit. When the callback is invoked you are sure the message was delivered, so at that point it is safe to disconnect.