I am trying to build a websocket server step by step. But I meet crucial problem when I try to use eventlet or gevent.
There are my codes for the server:
[uwsgi.ini]
[uwsgi]
chdir = /home/user/websocket
module=websocket:app
callable=app
processes=4
socket=/home/user/websocket/uwsgi.sock
uid = user
gid = user
chmod-socket=664
http-socket = :15000
log-reopen=true
die-on-term=true
master=true
vacuum=true
plugin=python3
virtualenv = /home/user/websocket/web
gevent = 100
[websocket.py]
from flask import Flask
from flask_socketio import SocketIO, send, emit
app = Flask(__name__)
socketio = SocketIO(app, logger=True, engineio_logger=True, cors_allowed_origins='*')
@socketio.on('connect')
def connected():
print('-'*30, '[connect]', '-'*30)
@socketio.on('message')
def handle_message(data):
print('-'*30, '[message]', '-'*30)
print('received message: ' + data)
send(data) # Echoes back the received message
@socketio.on_error() # This decorator handles all errors including connect_error
def handle_error(e):
if isinstance(e, Exception):
print('An error occurred:', str(e))
# Here, you can log the error or perform any necessary action.
# For example, you can check if it's a connect_error and take appropriate action.
@app.route("/")
def hello():
return "Connected"
if __name__ == '__main__':
socketio.run(app)
I ran:
uwsgi --ini uwsgi.ini
But I got the error:
Traceback (most recent call last):
File "/home/user/websocket/web/lib/python3.10/site-packages/flask/app.py", line 1478, in __call__
return self.wsgi_app(environ, start_response)
File "/home/user/websocket/web/lib/python3.10/site-packages/flask_socketio/__init__.py", line 43, in __call__
return super(_SocketIOMiddleware, self).__call__(environ,
File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/middleware.py", line 63, in __call__
return self.engineio_app.handle_request(environ, start_response)
File "/home/user/websocket/web/lib/python3.10/site-packages/socketio/server.py", line 428, in handle_request
return self.eio.handle_request(environ, start_response)
File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/server.py", line 271, in handle_request
packets = socket.handle_get_request(
File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/socket.py", line 90, in handle_get_request
return getattr(self, '_upgrade_' + transport)(environ,
File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/socket.py", line 146, in _upgrade_websocket
ws(environ, start_response)
File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/async_drivers/eventlet.py", line 40, in __call__
raise RuntimeError('You need to use the eventlet server. '
RuntimeError: You need to use the eventlet server. See the Deployment section of the documentation for more information.
So I tried to put "http-websockets = true" in the ini file but got the same error.
This is the client I tried
[index.html]
<!DOCTYPE html>
<html>
<head>
<title>Flask SocketIO Client</title>
<script src="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>
</head>
<body>
<input type="text" id="messageInput" placeholder="Type a message...">
<button onclick="sendMessage()">Send</button>
<div id="messages"></div>
<script>
var socket = io('http://localhost:15000'); // Change to your server's address and port
socket.on('connect', function() {
console.log('Connected to the server.');
});
socket.on('message', function(data) {
console.log('Received message:', data);
document.getElementById('messages').innerText += data + '\n';
});
function sendMessage() {
var message = document.getElementById('messageInput').value;
console.log('sending...:', message);
socket.emit('message', message);
document.getElementById('messageInput').value = '';
}
</script>
</body>
</html>
[client.py]
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(port=5001) # Run on a different port than your SocketIO server
In the client page, it shows this error:
POST http://localhost:15000/socket.io/?EIO=4&transport=polling&t=Ondmm8T&sid=BooMMCC89x9oei5_AAAQ 400 (BAD REQUEST)
websocket.js:88 WebSocket connection to 'ws://localhost:15000/socket.io/?EIO=4&transport=websocket&sid=1_GSTZsrzqFdezzbAAAP' failed:
Please help me to solve this problem.
It sounds like you have several supported libraries installed, so Socket.IO needs to know which of them you want to use. The default one is eventlet, but you are using uWSGI, so you have to tell it to use the uWSGI logic explicity by adding
async_mode='gevent_uwsgi'to yourSocketIO()constructor.I also recommend that you look at the documentation to learn how to configure for uWSGI. Multiple worker processes are not supported in the way that you are doing it, you should run a single worker, which can handle hundreds/thousands of concurrent clients through gevent.