How to emit message from python server to javascript client in python-socketio?
Asked Answered
E

1

6

The socketio client successfully connects to the server and sends messages with emit to the server but the other direction server to the client fails. I cannot find the source of error. It is

Here is the server python in app.py based on the example in python-socketio website:

from aiohttp import web
import socketio

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

async def index(request):
    """Serve the client-side application."""
    with open('index.html') as f:
        return web.Response(text=f.read(), content_type='text/html')

@sio.on('connect', namespace='/chat')
def connect(sid, environ):
    print("connect", sid)

@sio.on('chat message', namespace='/chat')
async def message(sid, data):
    print("server received message!", data)
    await sio.emit('reply', data)
    await sio.send(data)

@sio.on('disconnect', namespace='/chat')
def disconnect(sid):
    print('disconnect', sid)

app.router.add_static('/static', 'static')
app.router.add_get('/', index)

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

I tried commenting one of await sio.emit('reply', data) or await sio.send(data) but result was the same. Here is the javascript client in index.html:

<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script>
  </head>
  <body>
    <form id="the_form">
      <input type="input" name="msg" id="msg"></input>
      <input type="submit" value="➤"></input>
    </form>
    <script>
      var socket = io('http://localhost:8080/chat');

      socket.on('connect', function(){console.log('connect!')});
      socket.on('message', function(msg){console.log('message!', msg)});
      socket.on('disconnect', function(){console.log('disconnect!')});
      socket.on('reply', function(msg){console.log('reply!', msg)});

      document.getElementById('the_form').onsubmit = function(e) {
        let msg = document.getElementById('msg').value;
        document.getElementById('msg').value = '';

        // send it to the server
        socket.emit('chat message', msg);

        return false
      };
    </script>
  </body>
</html>

On the terminal window, I run the server. Then, I open two browser windows (Chrome Version 69.0.3497.100 (Official Build) (64-bit)) and send 'test' from one of them. Here is what I see on each window:

Terminal

$ python3 app.py 
======== Running on http://0.0.0.0:8080 ========
(Press CTRL+C to quit)
connect 9b18034f7b8b4d4c857dec394ef01429
connect 3adea48a3e00459f807855da0337599c
server received message! test

Window 1 (console log)

connect!

Window 2 (console log)

connect!
Evalynevan answered 12/10, 2018 at 23:31 Comment(6)
try doing await sio.emit('reply', room=sid) and just delete await sio.send(data)Deckert
OK, I did that. didn't work. I also tried sio.enter_room(sid, 'test_room') in connect function and await sio.emit('reply', room='test_room') as a way to send the message to the other client instead of echoing it. but none of them worked so far.Evalynevan
what about this one await sio.emit('reply', data, room=sid)Deckert
yes, sorry I meant that.Evalynevan
Check these exemples from the official github page github.com/miguelgrinberg/python-socketio/tree/master/examples I don't know witch one apply to your case.Deckert
Thanks for the link. these examples worked. I think I found the problem.Evalynevan
E
2

Based on the examples here suggested in comments by evgeni-fotia, the namespace argument is necessary here. It seems the default namespace, at least on this version, is not the namespace of the async function. So, the correct way to broadcast with echo back a message is the following:

@sio.on('chat message', namespace='/chat')
async def message(sid, data):
    print("server received message!", data)
    await sio.emit('reply', data, namespace='/chat')
Evalynevan answered 13/10, 2018 at 10:36 Comment(2)
as of Y2023 it seems better to update socket.io.min.js and get rid of line app.router.add_static('/static', 'static') as it is not immediately clear what is it for.Patel
for testing I had to correct this line as well: sio = socketio.AsyncServer(cors_allowed_origins='*')Patel

© 2022 - 2024 — McMap. All rights reserved.