简体   繁体   中英

Can't initialise concurrent websocket connections [eventlet, Flask, javascript]

I'm working on websockets using a serverside endpoint written in Python using eventlet and a client-side startpoint written in JavaScript:

var ws = new WebSocket("ws://192.168.1.25:16081/some_url");
ws.onopen = function()
{
  console.log("Transmitting " + data)
  ws.send(data)
};

ws.onmessage = function (evt)
{
    console.log(evt.data)
    // Do stuff with evt.data
};

And the Python code:

import eventlet
eventlet.sleep()
from eventlet import wsgi
from eventlet import websocket
from eventlet.support import six

@websocket.WebSocketWSGI
def game_room(ws):
    print(ws)
    try:
        while True:
            time.sleep(1)
            #Do stuff, some server-pushing
    except Exception,e:
        #Disconnect, do stuff

def dispatch(environ, start_response):
    """ This resolves to the web page or the websocket depending on
    the path."""
    if environ['PATH_INFO'] == '/some_url':
        return game_room(environ, start_response)


if __name__ == "__main__":
    # run an example app from the command line
    listener = eventlet.listen(('0.0.0.0', 16081))
    wsgi.server(listener, dispatch, debug=True)

I truncated some of the code for brevity. If I go to the page with the JavaScript, it works fine. The console that's running the wsgi server reports that a connection was made from the correct IP of the client machine. The problem is, if I use my phone to navigate to the same page, the socket doesn't report anything. If I close the tab on my machine and reload the socket server, I can connect with my phone. Somehow it doesn't seem to be able to handle concurrent connections.

I have no idea where to start. Can I edit some options when running the server?

Please reduce testing code to minimum and then paste it full. Don't hide parts of code. Truncated code leads us to the path of mystery guessing.

And my first guess is you have something like:

import time
import eventlet

def fun(name):
  while True:
    print('{0} tick'.format(name))
    time.sleep(1)

eventlet.spawn(fun, 'f1')
eventlet.spawn(fun, 'f2')
eventlet.sleep(10)

which only lets one coroutine to run, because time.sleep is blocking everything.

Please recognise code smell of using two different sleep functions. Always understand why and have a good reason to do that.

  • In this synthetic example, your best option is to use eventlet.sleep .
  • In real code sleep is hardly used at all, you'd rather react to flow of data than flow of time.
  • If you must call a blocking function written in pure Python, use eventlet.import_patched to have a green version of required module with all blocking functions fixed for coroutines.
  • If you must call a function that is blocking inside C module, use eventlet.tpool.execute to have it run in separate OS thread.

Unfortunately, this answer may be completely irrelevant if you truncated something like from eventlet.green import time and the problem is different.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM