【问题标题】:Sending data from express server to react-native client using socket.io使用 socket.io 将数据从 express 服务器发送到 react-native 客户端
【发布时间】:2020-04-15 14:52:24
【问题描述】:

我正在尝试使用 socket.io 将数据从我的 express 服务器发送到 react-native 客户端以实现一些实时功能。但是在阅读了多篇文章/stackoverflow 帖子后,我一直面临着一些我无法解决的问题。

我正在使用 ngrok 通过 expo 将我的 react-native 应用程序与服务器连接。应用程序中的其他功能正常工作,但客户端和服务器端套接字之间的连接未正确建立。

当我使用 IP 地址作为 URL ("http://192.ip.address.:8000") 来连接服务器和客户端上的套接字时,我可以看到 socket.connected 在我正在导入的所有 react-native 屏幕中都是正确的套接字客户端。但是没有收到消息。

另外,有没有更好的方法在服务器/客户端的多个文件之间共享同一个套接字实例/连接?

服务器端代码

在 index.js 中设置 socket.io

const app = express();
const expressRouter = require("./routes");
const socketio = require("socket.io");

app.set("view engine", "ejs");
app.set("views", "./views");
app.use(express.urlencoded());
app.use("/", expressRouter);

const server = app.listen(port, function (err) {
  if (err) {
    console.log(`Failed to run the server: ${err}`);
    return;
  }
  console.log(`Server running successfully on port: ${port}`);
});

const io = socketio(server);
app.set("io", io);

通过其中一个控制器 (/controllers/homeController.js) 句柄发送消息 --> /home

module.exports.getHome = function (request, response) {
  let io = request.app.get("io");

  io.on("connection", function (socket) {
    console.log("connected io");
    io.sockets.emit("some-channel", "some other new message text");
  });
  return response.render("dashboard");
};

React-Native 代码

设置套接字客户端以在所有屏幕中使用 (src/utils/socket.js)

import Constants from "./Constants";
import io from "socket.io-client";
export const socket = io(Constants.getNgrokUrl());

在其他屏幕(src/screens/homeScreen.js)中使用 socket.io 客户端

import { socket } from "../utils/socket";

const HomeScreen = ({ navigation }) => {
    const [socketData, setSocketData] = useState(""); 
    console.log("socket connection", socket.connected, "on home screen");

    socket.on("some-channel", function (data) {
      console.log("new data received", data);
      setSocketData(data);
    });

  return (
    <View>
       <Text>{socketData}</Text>
   </View>
);
};

【问题讨论】:

    标签: node.js react-native express socket.io


    【解决方案1】:

    您可以创建一个单例类来处理这个问题。在我的应用程序中,我使用如下

    import io from 'socket.io-client';
    import { SOCKET_SERVER } from './Constant';
    import async from 'async';
    
    export default class SocketInstance {
        static instance = null;
        static socketConn = null;
        static online = false;
    
        static getInstance(){
            if(SocketInstance.instance === null){
                SocketInstance.instance = new SocketInstance();
                SocketInstance.getSocket();
            }
            return this.instance;
        }
    
        static getSocket(){
            if(SocketInstance.socketConn === null){
                SocketInstance.socketConn = io.connect(SOCKET_SERVER,{ forceNew: true });
                const handshake = {
                        username: results.username,
                        client: results.client,
                        database:[{ last_updated_time: new Date(), table_name:'TODO-later' }]
                    };
                    SocketInstance.socketConn.on('connect',()=>{
                        console.warn('socket running in shared instance');
                        SocketInstance.socketConn.emit('*',handshake);
                        SocketInstance.online = true;
                    });
                    SocketInstance.socketConn.on('disconnect',()=>{
                        console.warn('--socket disconnected in shared instance--');
                        SocketInstance.online = false;
                    });
            }
            return this.socketConn;
        }
    
        send(message, data){
            if(SocketInstance.socketConn !== null){
                SocketInstance.socketConn.emit(message,data);
            }else{
                SocketInstance.getSocket();
            }
        }
    
        listen(message,func){
            if(SocketInstance.socketConn !== null){
                SocketInstance.socketConn.on(message,(data)=>{
                    func(data);
                });
            }else{
                SocketInstance.getSocket();
            }
        }
    
        isOnline(){
            if(SocketInstance.socketConn !== null){
                if(SocketInstance.socketConn.connected === false){
                    SocketInstance.getSocket();
                }
                return SocketInstance.socketConn.connected;
            }else{
                SocketInstance.getSocket();
                return false;
            }
        }
    }
    

    在您的屏幕中,您可以执行以下操作

    const socket = SocketInstance.getInstance();
    socket.send('*',{ data });
    socket.listen('data',(res)=>{
        console.warn(res);
    });
    

    但是...请记住在您的 index.jsApp.js 文件中调用以下行。我的意思是当应用加载时

    SocketInstance.getInstance();
    

    【讨论】:

      【解决方案2】:

      在尝试将客户端连接到它之前,必须关闭服务器端的防火墙连接。这是因为如果防火墙关闭,客户端只能连接到服务器的某个端口。

      对于问题的第二部分,您可以通过在 Heroku 等托管平台上托管应用程序来进行多个连接。但是,如果您处于开发阶段,则不建议这样做,因为这是一个更复杂的过程。因此,在这个阶段,ngrok 更可取。如果您使用的是带有 react native 的 android 模拟器,那么没有 ngrok 的普通 http 请求链接也可以工作。

      【讨论】:

        猜你喜欢
        • 2021-01-26
        • 2021-11-11
        • 1970-01-01
        • 1970-01-01
        • 2017-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多