Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client is getting socketio.exceptions.BadNamespaceError after reconnecting #920

Closed
ethanhjennings opened this issue May 1, 2022 · 2 comments
Labels

Comments

@ethanhjennings
Copy link

ethanhjennings commented May 1, 2022

Describe the bug
I have a client using python-socketio connected to a flask socketio server. When test stopping the server process and re-running it, the client throws 'BadNamespaceError'. I believe it may have something to do with the fact that the server listens to 'connect' events and then immediately broadcasts a 'get_state' event, so the client gets a 'get_state' right after re-connecting? Is this a bug and if not can I do anything to avoid it?

Here's my cut down code which still produces the error:
Client code:

import socketio

sio = socketio.Client(logger=True, engineio_logger=True)
sio.connect('http://localhost')

state = {'enabled': True, 'brightness': 100}

@sio.on('get_state')
def get_state():
    sio.emit('state', state)

Flask socketio server:

from flask import Flask, send_file, send_from_directory, g
from flask_socketio import SocketIO, emit

app = Flask(__name__)
socketio = SocketIO(app)

# <removed app routes for brevity>

@socketio.on('connect')
def handle_connect(auth):
    emit('get_state', broadcast=True)

@socketio.on('display_state')
def handle_enable(data):
    emit('display_state', data, broadcast=True)

if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=80)

To Reproduce
Steps to reproduce the behavior:

  1. Run the client and server
  2. Close and re-run the server
  3. Refresh the page for the javascript web-client

Expected behavior
This exception shouldn't be raised

Logs

Attempting polling connection to http://localhost/socket.io/?transport=polling&EIO=4
HTTP GET request to http://localhost/socket.io/?transport=polling&EIO=4&t=1651419962.4930985 failed with error HTTPConnectionPool(host='localhost', port=80): Max retries exceeded with url: /socket.io/?transport=polling&EIO=4&t=1651419962.4930985 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0xb58c3930>: Failed to establish a new connection: [Errno 111] Connection refused')).
Connection failed, new attempt in 4.48 seconds
Attempting polling connection to http://localhost/socket.io/?transport=polling&EIO=4
Polling connection accepted with {'sid': 'Vt0J-jFigQOcqG09AAAC', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000}
Engine.IO connection established
Sending packet MESSAGE data 0{}
Attempting WebSocket upgrade to ws://localhost/socket.io/?transport=websocket&EIO=4
WebSocket upgrade was successful
Received packet NOOP data
Received packet MESSAGE data 2["get_state"]
Received event "get_state" [/]
Received packet MESSAGE data 0{"sid":"uFO21x0B5h8VvGtZAAAD"}
Namespace / is connected
Reconnection successful
Exception in thread Thread-8:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.7/dist-packages/socketio/client.py", line 705, in _handle_eio_message
    self._handle_event(pkt.namespace, pkt.id, pkt.data)
  File "/usr/local/lib/python3.7/dist-packages/socketio/client.py", line 581, in _handle_event
    r = self._trigger_event(data[0], namespace, *data[1:])
  File "/usr/local/lib/python3.7/dist-packages/socketio/client.py", line 629, in _trigger_event
    return self.handlers[namespace][event](*args)
  File "test_socket.py", line 22, in get_state
    sio.emit('state', state)
  File "/usr/local/lib/python3.7/dist-packages/socketio/client.py", line 394, in emit
    namespace + ' is not a connected namespace.')
socketio.exceptions.BadNamespaceError: / is not a connected namespace.

Additional context
I've seen #634 but that was for an older version I think. I'm using 5.6.0 from pip. Also, this issue doesn't happen after connecting the first time, only after a disconnect and reconnect.

@miguelgrinberg
Copy link
Owner

I think the problem here is in your interpretation of what is the purpose of the connect handler in the server. This handler is used to accept or reject a connection. In other words, the connection is not fully established until the connect handler returns.

Your connect handler is emitting an event to the client. Then you have your client emit back. The emit from client to server fails, because the namespace connection is not going to be established fully until after the connect handler returns.

An alternative that you can try is to add the always_connect option to the server. This changes the way the connection flow works. When this option is used, all connections are immediately accepted, before the connect handler is invoked, so by the time the connect handler is called, the connection is established.

@ethanhjennings
Copy link
Author

ethanhjennings commented May 2, 2022

Thank you! Adding always_connect=True to the server fixed my issue! 👏

hcadavid added a commit to vantage6/vantage6 that referenced this issue Jun 14, 2024
…' option when the server creates SocketIO objects as discussed on miguelgrinberg/python-socketio#920. This fixes issue #1333
hcadavid added a commit to vantage6/vantage6 that referenced this issue Jun 14, 2024
…' option when the server creates SocketIO objects as discussed on miguelgrinberg/python-socketio#920.

This fixes issue #1333 (comming including blackformatting)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants