【问题标题】:Custom room Socket.io NodeJS自定义房间 Socket.io NodeJS
【发布时间】:2021-11-01 22:05:19
【问题描述】:

我正在制作一个带有套接字的应用程序,并且需要广播信息,但仅限于房间内的人。

这是我来自server.ts的代码

// Dependencies
import express from 'express'
import http from 'http'
import socket from 'socket.io';
import {connect, disconnect, orderChanged} from './sockets/socket';
import {config} from 'dotenv';

config ();

// Main class
export default class server {

    _private static instance: server
    public app: express.Application
    public port: number
    http: http.Server private
    public io: socket.Server

    // Initialize variables and methods
    // Singleton pattern implementation
    private constructor () {

        this.app = express ()
        this.port = Number (process.env.SRV_PORT)
        this.http = new http.Server (this.app)
         this.io = new socket.Server (this.http, {
            cors: {
                origin: true,
                credentials: true
            }
        })
        this.listenSockets ();
    }

    // Return the instance running Singleton pattern
    public static get instance () {
        returns this._instance || (this._instance = new Server ())
    }

    // Method to start the server
    start (callback: any) {
        this.http.listen (this.port, callback)
    }

    private listenSockets (): void {
        console.log ('Listening Sockets');

        this.io.on ('connection', client => {
            console.log ('Connected to room', client.rooms, '-', client.id);
            // User disconnected
            disconnect (client);
            connect (client);
        });
    }
}

节点启动后,在 DP Singleton 中创建一个实例并启动套接字侦听器 当数据库中发生操作时,应用程序中的任何位置,我将其发送给调用并将信息发送到前端,前端正确接收并执行它必须做的事情。示例url / edit-products

import server from '../core/server';

// Socket broadcast, new information
const __id = String (req.headers.id);
const updatedData = await getNewData (__id);
Server.instance.io.emit ('data changed', updatedData);

问题是这个信息被不加选择地发送给所有连接到套接字的用户。现在,我有一个唯一的 ID,可以将多个用户聚集在一个 MongoDB 模型中。您可以使用该 ID 仅向具有该 ID 的用户广播。有一个逻辑暗示,如果用户从墨西哥连接,则将其添加到 MongoDB 中的 Array of people 中,否则它将添加到另一个 MongoDB 文档中,那么它们是两个不同的 ID。 我希望房间是那个 ID。

我看到我可以使用套接字的join () 方法,但该函数来自连接的客户端,而不是来自服务器本身。我尝试发布这样的信息

// Socket broadcast, new information
const __id = String (req.headers.id);
const updatedData = await getNewData (__id);
Server.instance.io.in (updatedData._id) .emit ('data changed', updatedData);

但我从来没有设置过那个“房间”。当用户登录时,他可以添加它但我不知道如何创建自定义房间,他尝试了这样的事情

const user = await UserModel.find (_data);
Server.instance.io.join (user.channel._id);

但是 io 中的那个函数不存在。

它存在这种方式,但它对我不起作用

Server.instance.io.on ('user-join', (socket: Socket) => {
   console.log (plug);
   socket.join (uuid);
});
Server.instance.io.emit ('user join');

我能做什么?

【问题讨论】:

    标签: node.js typescript express socket.io


    【解决方案1】:

    .join() 是单个套接字上的方法。这就是您将其用作socket.join(roomName) 的方式。当第一个用户加入房间时,房间会自动创建,其他用户也可以加入。当最后一个用户离开房间时,房间会自动从服务器中删除。因此,您将用户的套接字连接到房间 - 您不会将某些内容连接到服务器。


    同样,当您尝试这样做时:

    Server.instance.io.on ('user-join', (socket: Socket) => {
       console.log (plug);
       socket.join (uuid);
    });
    

    这不起作用,因为您不监听来自服务器上套接字的传入消息(connection 消息除外 - 它引入了套接字对象)。您在套接字本身上侦听传入的客户端消息:

    Server.instance.io.on ('connection', (socket: Socket) => {
        socket.on('user-join', () => {
            // you will have to find the room name that goes with this socket
            socket.join(someRoomName);
        });
    });
    

    另外,请注意这段代码:

    private listenSockets (): void {
        console.log ('Listening Sockets');
    
        this.io.on ('connection', client => {
            console.log ('Connected to room', client.rooms, '-', client.id);
            // User disconnected
            disconnect (client);
            connect (client);
        });
    }
    

    看起来有问题。为什么当他们连接时你会断开客户端?您没有显示disconnect()connect() 的这些功能,因此不清楚它们实际上在做什么——我猜它们会以某种方式跟踪连接的客户端。如果您只是想清理之前可能挂起的任何状态,那么您应该执行以下操作:

    private listenSockets (): void {
        console.log ('Listening Sockets');
    
        this.io.on ('connection', client => {
            console.log ('Connected to room', client.rooms, '-', client.id);
            client.on('disconnect', () => {
                // User disconnected
                disconnect(client);
            });
    
            // user connected now
            connect(client);
        });
    }
    

    您不必担心关于套接字是否已连接的不准确管理。当套接字断开连接时,您总是会收到一个disconnect 事件。这有两个原因。对于关闭的浏览器窗口或用户导航离开的页面,浏览器会清除与该页面关联的所有对象,包括打开的 socket.io 连接。这将始终关闭套接字并导致disconnect 事件。其次,socket.io 使用pingpong 消息定期检查现有连接是否仍在工作。如果不是,它将断开连接。根据具体情况,客户端可能会或可能不会重试打开新连接。但是,任何功能不正常的连接(不响应ping 消息的连接)都将被服务器关闭,并且也会发生disconnect 事件。因此,这两种情况可确保始终发生 disconnect 事件。

    Server.instance.io.emit ('data changed', updatedData);问题是这个信息被不加选择地发送给所有连接到套接字的用户。

    这会发送给连接到您服务器的所有用户,这就是它的设计方式。

    要发送到单个套接字,您可以使用:

     socket.emit(...);
    

    其中socket 是您的代码调用client,您从connection 事件中获得的对象。

    要发送到已加入房间的所有套接字,您可以使用:

     io.in(roomName).emit(...)
    

    io 是 socket.io 服务器实例。

    而且,.emit() 的变体还有很多很多,具体取决于您要发送的具体内容。

    现在,我有一个唯一的 ID,可以在 MongoDB 模型中将多个用户聚集在一起。您可以使用该 ID 仅向具有该 ID 的用户广播。有一个逻辑暗示,如果用户从墨西哥连接,则将其添加到 MongoDB 中的 Array of people 中,否则它将添加到另一个 MongoDB 文档中,那么它们是两个不同的 ID。我希望房间是那个 ID。

    我没有完全按照你的想法去做,但似乎在你的 connect(client) 函数中,你可以调用 client.join(uniqueIDForMultipleUsers) 并创建一个具有此唯一 ID 的房间并将此客户端添加到其中房间。以后,您可以通过io.in(uniqueIDForMultipleUsers).emit(...) 发送给该房间中的每个人。

    但我从来没有设置过那个“房间”。当用户登录时,他可以添加它但我不知道如何创建自定义房间,他尝试了这样的事情

    您无需手动创建房间。您只需使用socket.join(roomName),如果房间不存在,socket.io 基础架构会自动创建房间。同样,当房间中的最后一个插座离开房间或断开连接时,房间会自动移除。因此,您不必自己管理房间的创建或删除。事实上,一个房间对象不是你直接处理的东西——它是 socket.io 服务器内部的一个管家项目,它包含一个当前在房间中的套接字列表。一个插座可以在任意多个房间中。你在服务器上使用这些:

    socket.join(roomName);     // add a client's socket to a room
    socket.leave(roomName);    // remove a client's socket from a room
    io.in(roomName).emit(...); // broadcast a message to every socket in a room
    

    上面的逻辑有时有点令人困惑的是socket.join()socket.leave() 是套接字方法,但它们实际上修改了服务器中的数据结构(房间/套接字列表被保存的地方)。无论出于何种原因,这就是他们选择最初设计 API 的方式。从逻辑上讲,它更像io.join(socket, roomName),因为它正在修改服务器上的某些内容。但是,由于套接字知道它所属的服务器对象,他们可以将其关闭,只需执行socket.join(roomName)

    【讨论】:

      猜你喜欢
      • 2019-05-13
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-20
      • 2013-04-04
      • 2021-03-02
      • 1970-01-01
      相关资源
      最近更新 更多