reactjs 客户端和 flask-socketio 服务器之间的 WebSocket 连接未打开
WebSocket connection between reactjs Client and flask-socketio Server doesn't open
在我的项目中,我使用了 React 前端和带有 RESTful API 的 Flask 服务器。基本功能是前端从服务器获取数据并显示。这工作正常,但我想我会通过让客户端在服务器从其他地方接收到新数据时自动重新获取来改进它。我可以使用轮询并每隔一段时间发出一个获取请求,但这似乎是 WebSockets 的完美用例。因此,我正在尝试在服务器和客户端之间实现一个 websocket 连接,当某些事件发生时,服务器会向客户端发送一条消息。
我的服务器是用 python 用 Flask 编写的,使用特定于 Flask 的 websocket 库似乎是个好主意。我最终使用了 flask-socketio,但我在使用它时遇到了问题。我的服务器相关部分如下:
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
... # Server functionality for receiving and storing data from elsewhere, not related to the websocket
# Handle the webapp connecting to the websocket
@socketio.on('connect')
def test_connect():
print('someone connected to websocket')
emit('responseMessage', {'data': 'Connected! ayy'})
# Handle the webapp connecting to the websocket, including namespace for testing
@socketio.on('connect', namespace='/devices')
def test_connect2():
print('someone connected to websocket!')
emit('responseMessage', {'data': 'Connected! ayy'})
# Handle the webapp sending a message to the websocket
@socketio.on('message')
def handle_message():
print('someone sent to the websocket')
# Handle the webapp sending a message to the websocket, including namespace for testing
@socketio.on('message', namespace='/devices')
def handle_message2():
print('someone sent to the websocket!')
@socketio.on_error_default # handles all namespaces without an explicit error handler
def default_error_handler(e):
print('An error occured:')
print(e)
if __name__ == '__main__':
socketio.run(app, debug=True, host='0.0.0.0')
对于前端,我最初也尝试使用库。我选择了 react-websocket。
<Websocket
url={'ws://localhost:5000'} // I also tried /devices at the end of this url
onMessage={() => console.log('Received message through websocket.')}
debug={true}
/>
但是,这个解决方案连接后立即断开连接,这意味着有问题。不过,要找出到底出了什么问题似乎是不可能的;尽管 debug={true}
,但我在日志中没有任何指示。我没有使用这个解决方案,而是为前端换用了一个更自定义的 WebSocket 解决方案:
componentDidMount() {
moment.locale('nb');
jsonRequest(irrelevant url).then(jsonResponse => {
... // Handle the results of the initial fetch
const socket = new WebSocket('ws://localhost:5000'); // I also tried /devices at the end of this url
socket.onopen = () => console.log('opened custom socket');
socket.onclose = () => console.log('closed custom socket');
socket.onmessage = e => console.log('got message');
socket.onerror = e => console.log('websocket error');
socket.addEventListener('open', function(event) {
console.log('sending');
socket.send('Hello Server!');
});
socket.addEventListener('message', function(event) {
console.log('Message from server ', event.data);
});
this.socket = socket;
this.setState(...);
});
}
这个解决方案有同样的问题。我的控制台输出如下:
Rendering...
是我放在渲染函数最顶部的控制台语句。
所以在这两种方案中,客户端连接后立即断开websocket连接。我的服务器也没有注意到任何东西。 None 的事件处理程序触发器 - 不是 @socketio.on('connect')
,不是 @socketio.on('message')
,甚至 @socketio.on_error_default
。因此,我发现自己遇到了障碍。我如何从这里调试?可能是什么问题?我在 Ubuntu 服务器上尝试了完全相同的代码,所以我 认为 localhost 不是问题所在。
您将 Socket.IO 与 WebSocket 混淆了。 Socket.IO 协议建立在 WebSocket 和 HTTP 之上。您的连接失败是由于您使用普通 WebSocket 客户端连接到 Socket.IO 服务器造成的。您需要使用 Socket.IO 客户端,例如 this one.
在我的项目中,我使用了 React 前端和带有 RESTful API 的 Flask 服务器。基本功能是前端从服务器获取数据并显示。这工作正常,但我想我会通过让客户端在服务器从其他地方接收到新数据时自动重新获取来改进它。我可以使用轮询并每隔一段时间发出一个获取请求,但这似乎是 WebSockets 的完美用例。因此,我正在尝试在服务器和客户端之间实现一个 websocket 连接,当某些事件发生时,服务器会向客户端发送一条消息。
我的服务器是用 python 用 Flask 编写的,使用特定于 Flask 的 websocket 库似乎是个好主意。我最终使用了 flask-socketio,但我在使用它时遇到了问题。我的服务器相关部分如下:
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
... # Server functionality for receiving and storing data from elsewhere, not related to the websocket
# Handle the webapp connecting to the websocket
@socketio.on('connect')
def test_connect():
print('someone connected to websocket')
emit('responseMessage', {'data': 'Connected! ayy'})
# Handle the webapp connecting to the websocket, including namespace for testing
@socketio.on('connect', namespace='/devices')
def test_connect2():
print('someone connected to websocket!')
emit('responseMessage', {'data': 'Connected! ayy'})
# Handle the webapp sending a message to the websocket
@socketio.on('message')
def handle_message():
print('someone sent to the websocket')
# Handle the webapp sending a message to the websocket, including namespace for testing
@socketio.on('message', namespace='/devices')
def handle_message2():
print('someone sent to the websocket!')
@socketio.on_error_default # handles all namespaces without an explicit error handler
def default_error_handler(e):
print('An error occured:')
print(e)
if __name__ == '__main__':
socketio.run(app, debug=True, host='0.0.0.0')
对于前端,我最初也尝试使用库。我选择了 react-websocket。
<Websocket
url={'ws://localhost:5000'} // I also tried /devices at the end of this url
onMessage={() => console.log('Received message through websocket.')}
debug={true}
/>
但是,这个解决方案连接后立即断开连接,这意味着有问题。不过,要找出到底出了什么问题似乎是不可能的;尽管 debug={true}
,但我在日志中没有任何指示。我没有使用这个解决方案,而是为前端换用了一个更自定义的 WebSocket 解决方案:
componentDidMount() {
moment.locale('nb');
jsonRequest(irrelevant url).then(jsonResponse => {
... // Handle the results of the initial fetch
const socket = new WebSocket('ws://localhost:5000'); // I also tried /devices at the end of this url
socket.onopen = () => console.log('opened custom socket');
socket.onclose = () => console.log('closed custom socket');
socket.onmessage = e => console.log('got message');
socket.onerror = e => console.log('websocket error');
socket.addEventListener('open', function(event) {
console.log('sending');
socket.send('Hello Server!');
});
socket.addEventListener('message', function(event) {
console.log('Message from server ', event.data);
});
this.socket = socket;
this.setState(...);
});
}
这个解决方案有同样的问题。我的控制台输出如下:
Rendering...
是我放在渲染函数最顶部的控制台语句。
所以在这两种方案中,客户端连接后立即断开websocket连接。我的服务器也没有注意到任何东西。 None 的事件处理程序触发器 - 不是 @socketio.on('connect')
,不是 @socketio.on('message')
,甚至 @socketio.on_error_default
。因此,我发现自己遇到了障碍。我如何从这里调试?可能是什么问题?我在 Ubuntu 服务器上尝试了完全相同的代码,所以我 认为 localhost 不是问题所在。
您将 Socket.IO 与 WebSocket 混淆了。 Socket.IO 协议建立在 WebSocket 和 HTTP 之上。您的连接失败是由于您使用普通 WebSocket 客户端连接到 Socket.IO 服务器造成的。您需要使用 Socket.IO 客户端,例如 this one.