ReactJS客户端和flask-socketio服务器之间的WebSocket连接无法打开

fin*_*nss 1 javascript python websocket reactjs flask-socketio

在我的项目中,我正在使用带有RESTful API的React前端和Flask服务器。基本功能是前端从服务器获取数据并显示它。这可以正常工作,但是我认为我可以通过使服务器每当服务器从其他地方接收到新数据时自动重新获取客户端来进行改进。我可以使用轮询并仅在一定间隔内触发获取请求,但这似乎是WebSockets的完美用例。因此,我正在尝试在服务器和客户端之间实现Websocket连接,当某些事件发生时,服务器会将消息发送到客户端。

我的服务器是用Flask用python编写的,使用特定于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')
Run Code Online (Sandbox Code Playgroud)

对于前端,我最初也尝试使用库。我选择了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}
/>
Run Code Online (Sandbox Code Playgroud)

但是,该解决方案在连接后立即断开连接,这表明出了点问题。确切地找出出了什么问题似乎是不可能的。尽管我没有记录在日志中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(...);
    });
}
Run Code Online (Sandbox Code Playgroud)

该解决方案具有相同的问题。我的控制台输出如下: 控制台输出

Rendering...是我在渲染功能最顶部放置的控制台语句。

因此,在这两种解决方案中,客户端在连接后都会立即从websocket连接中断开连接。我的服务器也什么也没注意到。没有事件处理程序触发-不@socketio.on('connect'),不@socketio.on('message'),甚至不触发@socketio.on_error_default。因此,我发现自己处于障碍之中。我如何从这里调试?可能是什么问题?我已经在Ubuntu服务器上尝试了相同的代码,所以我认为本地主机不是问题。

Mig*_*uel 5

您正在将Socket.IO与WebSocket混淆。Socket.IO协议建立在WebSocket和HTTP之上。您使用普通的WebSocket客户端连接到Socket.IO服务器会导致连接失败。您需要使用Socket.IO客户端,就像这样