Chat App、React Native 和 FlaskBackend 以及 flask_socketio 的问题

Issues with Chat App , React Native and FlaskBackend and flask_socketio

我正在尝试创建一个项目,其中一项功能是聊天。聊天的结构是:在 React Native 中制作的应用程序和我使用 Flask 的后端。对于后端,我有许多不同的路由,我的目的是创建另一个路由来使用 WebSocket 处理用户消息。 flask_socketio 我有很多问题。我使用 NodeJs 尝试了一个小版本的 websocket,它工作得很好。这就是我到目前为止所做的:

RN app(frontend):
import SocketIOClient from 'socket.io-client'
import {GiftedChat} from 'react-native-gifted-chat'
export default class ChatScreen extends React.Component{
    static navigationOptions = ({ navigation }) => {
            return{
                title:`${navigation.getParam('mTitle')}`
            }
    }
    state={
        messages:[]
    }

    constructor(props){
      super(props)
      this.socket = SocketIOClient('http://a960eba8.ngrok.io');
      // this.socket.on('message', this.onReceivedMessage);
      this.socket.on("chat_message", msg => {
        console.log('mensagem recebida: ',msg)
        // this.setState({ chatMessages: [...this.state.chatMessages, msg] });
      });
    }
    componentDidMount() {
      console.log('component did mount function')
        this.setState({
          messages: [
            {
              _id: 1,
              text: 'Hello developer',
              createdAt: new Date(),
              user: {
                _id: 2,
                name: 'React Native',
                avatar: 'https://placeimg.com/140/140/any',
              },
            },
          ],
        })

      }
      onReceivedMessage = (message)=>{
        console.log('message received:',message)
      }
      onSend(messages = []) {
        this.setState(previousState => ({
          messages: GiftedChat.append(previousState.messages, messages),
        }))
        let msg = messages[0].text
        console.log('emit message: ',msg)
        this.socket.emit('chat_message',{message:msg})
        console.log('quite done')
      }

      render() {
        return (
            <GiftedChat
            messages={this.state.messages}
            onSend={messages => this.onSend(messages)}
            user={{
              _id: 1,
            }}
            />
        )
      }
}

我尝试测试的节点后端...

const express = require("express");
const app = express();
const server = require("http").createServer(app);
const io = require("socket.io").listen(server);
const port = 3000;
const ws_event = "chat_message"
console.log('novo cod...')
io.on("connection", socket => {
  console.log("a user connected :D");
  socket.on(ws_event, msg => {
    console.log(msg);
    io.emit(ws_event, msg);
  });
});

server.listen(port, () => console.log("server running on port:" + port));

Flask 后端:

...
app = config_server() # flask app
db = app.db
m_test_room = 'm_room_123'
Session(app)
##----------------------------------------------------------------##
True,manage_session = True)
socketio = SocketIO(app,manage_session = False)

def estrutura_server():
    from src.util.util_outros import cria_pastas_necessarias
    cria_pastas_necessarias()
    pass

# api = create_api(app) # swagger
if __name__ == '__main__':
    estrutura_server()
    configure_websocket(socketio, app)
    if set_is_debug() is False:
        port = int(os.environ.get('PORT'))
        logging.debug('running on heroku, port: ', port)
        app.run(host='0.0.0.0', port=port)
    else:
        app.run(host='localhost', port = 3000, debug=True)

    # socketio.run(host="localhost", port=3000, debug=True, app=app)

配置websocket函数:

def configure_websocket(socketio_object,flask_app):
    from src.resources.reatime_resources.chatsocketresources import SocketChat
    socketio_object.on_namespace(SocketChat(''))

用于处理 websocket 的命名空间:

from  flask_socketio import Namespace, emit

class SocketChat(Namespace):


    def on_join(self,**kwargs):
        print('join interno: ',kwargs)


    def on_connect(self,**kwargs):
        print('on connect interno')
        emit('chat_message','chegou aqui no backend')
        pass

    def on_chat_message(self,**kwargs):
        print('on chat message::',kwargs)
        emit('chat_message',kwargs)

也许值得一提的是,我正在使用 ngrok 在前端(移动应用程序)和后端之间建立隧道。 PyCharm 上的错误消息(对于烧瓶后端):

INFO:engineio.server:96d6a2bae8c94cd98ed4003c3b9bf53e: Sending packet OPEN data {'sid': '96d6a2bae8c94cd98ed4003c3b9bf53e', 'upgrades': ['websocket'], 'pingTimeout': 60000, 'pingInterval': 25000}
INFO:socketio.server:emitting event "chat_message" to all [/]
INFO:engineio.server:48d735483b7f4cd5b0efb60c5f0493cf: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:96d6a2bae8c94cd98ed4003c3b9bf53e: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:96d6a2bae8c94cd98ed4003c3b9bf53e: Sending packet MESSAGE data 0
INFO:werkzeug:127.0.0.1 - - [09/Feb/2020 08:44:06] "GET /socket.io/?EIO=3&transport=polling&t=N0fmuTD HTTP/1.1" 200 -
on connect interno
WARNING:engineio.server:Invalid session None
INFO:werkzeug:127.0.0.1 - - [09/Feb/2020 08:44:07] "POST /socket.io/?EIO=3&transport=polling&t=N0fmud0 HTTP/1.1" 400 -
INFO:engineio.server:ebfeb359a601499a8df9db58415092ed: Sending packet OPEN data {'sid': 'ebfeb359a601499a8df9db58415092ed', 'upgrades': ['websocket'], 'pingTimeout': 60000, 'pingInterval': 25000}
INFO:socketio.server:emitting event "chat_message" to all [/]
INFO:engineio.server:48d735483b7f4cd5b0efb60c5f0493cf: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:96d6a2bae8c94cd98ed4003c3b9bf53e: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:ebfeb359a601499a8df9db58415092ed: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:ebfeb359a601499a8df9db58415092ed: Sending packet MESSAGE data 0
INFO:werkzeug:127.0.0.1 - - [09/Feb/2020 08:44:12] "GET /socket.io/?EIO=3&transport=polling&t=N0fmvrF HTTP/1.1" 200 -
on connect interno
WARNING:engineio.server:Invalid session None
INFO:werkzeug:127.0.0.1 - - [09/Feb/2020 08:44:13] "POST /socket.io/?EIO=3&transport=polling&t=N0fmv-y HTTP/1.1" 400 -
INFO:engineio.server:87e52ce8da464b6a86c979e8dd2fd1a3: Sending packet OPEN data {'sid': '87e52ce8da464b6a86c979e8dd2fd1a3', 'upgrades': ['websocket'], 'pingTimeout': 60000, 'pingInterval': 25000}
INFO:socketio.server:emitting event "chat_message" to all [/]
INFO:engineio.server:48d735483b7f4cd5b0efb60c5f0493cf: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:96d6a2bae8c94cd98ed4003c3b9bf53e: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:ebfeb359a601499a8df9db58415092ed: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:87e52ce8da464b6a86c979e8dd2fd1a3: Sending packet MESSAGE data 2["chat_message","chegou aqui no backend"]
INFO:engineio.server:87e52ce8da464b6a86c979e8dd2fd1a3: Sending packet MESSAGE data 0
INFO:werkzeug:127.0.0.1 - - [09/Feb/2020 08:44:18] "GET /socket.io/?EIO=3&transport=polling&t=N0fmxD8 HTTP/1.1" 200 -
on connect interno

Android Studio 上 React Native 应用程序的错误消息:

W/unknown:ReactNative: failed to decode string from byte array
W/unknown:ReactNative: failed to decode string from byte array
W/unknown:ReactNative: failed to decode string from byte array

您遇到的 Invalid session None 错误在 React Native 前端很常见。有关同一问题的先前报告,请参阅 here, here and here

似乎可行的解决方法是要求 React Native Socket.IO 客户端直接与 WebSocket 连接。该问题仅在客户端通过 HTTP 连接然后升级到 WebSocket 时存在。这是一个直接使用 WebSocket 的示例连接:

SocketIOClient(`http://a960eba8.ngrok.io`, {transports: ['websocket']});