I'm using socket.io with python 3.10 (I'm using flask but not tied to it) and React for the front end. I seem to be connected okay, and the python server is aware of the pings coming in, but the message endpoints I've written don't get triggered.
Here is my python:
import socketio
from flask import Flask, render_template
# standard Python
sio = socketio.Server(
logger=True, engineio_logger=True, async_mode='threading',
# cors_allowd_origns="http://localhost:3000" # doesn't work for some reason
cors_allowed_origins="*"
)
app = Flask(__name__)
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=3001)
@sio.on('ping')
def ping(sid, data):
print('did a ping!')
print('ping', sid, data)
exit('this should fire')
And here's my React:
const App = () => {
const [isConnected, setIsConnected] = useState(socket.connected);
const [lastPong, setLastPong] = useState(null);
useEffect(() => {
socket.on('connect', () => {
console.log('connected')
setIsConnected(true);
});
socket.on('disconnect', () => {
console.log('disconnected')
setIsConnected(false);
});
socket.on('pong', () => {
console.log('pong')
setLastPong(new Date().toISOString());
});
socket.on('message', () => {
console.log('message')
});
return () => {
socket.off('connect');
socket.off('disconnect');
socket.off('pong');
};
}, []);
const sendPing = () => {
const message = {
id: 10,
user: 'alex',
time: Date.now(),
data: 'test',
};
console.log('ping', message);
// console.log('ping done');
socket.emit('ping', message);
// socket.send('hello');
}
// Render the Slate context.
return (
<div className='context-context'>
<p>Connected: { '' isConnected }</p>
<p>Last pong: { lastPong || '-' }</p>
<button onClick={ sendPing }>Send ping</button>
<div className='editor-context'>
<EditableInput></EditableInput> // this is defined elsewhere
</div>
</div>
)
}
I am able to connect okay, and when I press 'send ping', I get this:
received event "ping" from fpyAKmiwmwkO6tpoAAAB [/]
127.0.0.1 - - [01/Sep/2022 13:28:41] "POST /socket.io/?EIO=4&transport=polling&t=OBwlTWh&sid=ei_zgp4tafpqY35xAAAA HTTP/1.1" 200 -
But the code I've written in the ping
function does not get hit. What I am doing wrong?? I've wracked my brains and can't figure this one out.
CodePudding user response:
A solution that I don't fully understand seemed to work. Rather than run the script in the typical python main.py
or flask run
ways, I installed something called gunicorn (a unicorn with a gun?):
gunicorn -k gevent -b 127.0.0.1:3001 'main:app'
This seems to work. Any insight about why would be appreciated! I don't feel like I learned anything in this 24 hr experience.
CodePudding user response:
I don't know React
so I can't run your code to test it.
I think problem can be because you define ping
after app.run()
.
When you run flask
then first it runs app.run()
and it blocks rest of code and it can't execute @sio.on('ping')
to assign this function to socket. And ping
doesn't work.
I assumed you run it as python main.py
which runs it directly.
flask run
could work because it imports code.
This should work
import socketio
from flask import Flask, render_template
# standard Python
sio = socketio.Server(
logger=True, engineio_logger=True, async_mode='threading',
# cors_allowd_origns="http://localhost:3000" # doesn't work for some reason
cors_allowed_origins="*"
)
@sio.on('ping')
def ping(sid, data):
print('did a ping!')
print('ping', sid, data)
exit('this should fire')
# ---
app = Flask(__name__)
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=3001)
When you use gunicorn
then it doesn't run it directly but it imports code from main.py
. And import
always skips code inside if __name__ == '__main__':
and code can run @sio.on('ping')
.
And later gunicorn
will use own method to start app.run()