Socket.io在命名空间之间共享套接字数据

时间:2015-04-23 13:01:39

标签: javascript node.js socket.io

我想知道如何在一个命名空间中的套接字中共享数据并在另一个命名空间中访问它?

我完全清楚我可以将数据附加到套接字对象本身。当我将数据附加到一个名称空间并尝试在另一个名称空间访问它时,就会出现问题。

下面演示了问题

var io = require( 'socket.io' );

module.exports.init = function( server ) {

    io = io.listen( server );

    io.of( '/chatSystem' ).on( 'connection', function( socket ) {
        /*handling set nickname event*/
        socket.on( 'set.name', function( data ) {
            /*attach nickname key to this socket*/
            socket.nickname = data.name;
            socket.broadcast.emit( 'user.entered', data );
        });
    });

    io.of( '/chatUser').on( 'connection', function( socket ) {
        /*handling client event socket.send*/
        socket.on( 'message', function( data ) {
            data = JSON.parse( data );
            data.nickname = socket.nickname; // <--- this is undefined

            /*send to all connected client( broadcast will not send message to socket that created the message)*/
            socket.broadcast.send( JSON.stringify( data ) );
            data.type = 'myMessage';

            /*manually send back the message to the socket that created the message*/
            socket.send( JSON.stringify( data) );
        });
    });
};

有没有办法解决这个问题?

3 个答案:

答案 0 :(得分:4)

这可能有点晚了,但我只是偶然发现了一个更简单的解决方案,并认为我将为未来的调查人员分享。

with socket&gt; 1.0,您可以将共享数据存储在套接字的客户端对象中。它似乎仍然在套接字之间共享

使用上面的例子

<?php

$ch = curl_init();

$data = [
    'client_secret' => $YOUR_CLIENT_SECRET,
    'code' => $AUTH_CODE,
    'redirect_url' => $YOUR_REDIRECT_URI,
    'client_id' => $YOUR_CLIENT_ID,
    'grant_type' => 'authorization_code'
];//set your data as an array

$headers = [
    "Content-Type: application/x-www-form-urlencoded",
    "Authorization: bearer " . $access_token
];
$opts = [
    CURLOPT_URL => $url,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_SSL_VERIFYPEER => 0,
];
if ($request_type == 'post') {
    $opts[CURLOPT_POST] = 1;
    $opts[CURLOPT_POSTFIELDS] = http_build_query($data);// this will build your data string from the array
}

curl_setopt_array($ch, $opts);
$result = curl_exec($ch);
curl_close($ch);
return $result;

和检索

    /* attach nickname key to this socket */
    socket.client.nickname = data.name;
    /* In typescript with @types/socket.io */
    socket.client["nickname"] = data.name;

希望这可以帮助别人。我一直试图找到一个解决方案整个星期,并偶然发现这个线程。一个小时后,我发现了这个替代方案。

答案 1 :(得分:1)

  

更新我的答案以获得更加通用和“更安全”的解决方案

事实证明,我们可以跨命名空间共享数据,但我们必须通过将套接字实例从一次命名空间引用到另一个命名空间来实现。

假设有两个名称空间,即 namespace_A namespace_B

要从 namespace_B 中的 namepsace_A 获取相应的套接字对象,我们会使用当前的套接字 namespace_A 命名空间对象中连接的对象的对象ID(因为它类似)。

虽然这仍然是一种解决方法,但这是迄今为止我能够在命名空间之间共享会话数据的最佳和最安全的方式。

我们将使用socket.id来引用所需的套接字。 ID看起来像这样:/namespace#vCpuzzUi4RI1DHqfAAAH。 命名空间内的每个套接字实例都具有类似的ID,除了命名空间部分,i。例如,对于namespace_A,ID将类似于/namespace_A#vCpuzzUi4RI1DHqfAAAH,而对于namespace_B,它将是/namespace_B#vCpuzzUi4RI1DHqfAAAH。因此,如果我们可以生成类似于当前套接字的套接字ID并使用它,我们可以从另一个名称空间中引用一个套接字实例。

我们需要做的是首先在开头声明一个变量,如:

var self = this;

这用于保存对当前对象的引用。 接下来在一个名称空间中,假设 namespace_A ,我们需要通过在A:中编写此代码来从 namespace_B 的套接字实例中获取数据。

ns_b_socket = self.namespace_B.connected['/namespace_B#' + buildSocketID(socket.id)];

我们使用self.namespace_B引用当前实例的namespace_B,然后在其上调用已连接

  

命名空间#连接:对象

     

连接到此命名空间的Socket对象的哈希值   标识。

我使用自定义函数生成ID。

function buildSocketID(iden) {
    return iden.split('#')[1];  
}

现在,如果您从ns_b_socket.username致电namespace_A,则可以从 namespace_B 获取socket.username的值。

注意:适用于1.0.x及更高版本。对于此版本以下的版本,请参阅here

答案 2 :(得分:0)

嗨,我想到了一个workround。观看

var io = require( 'socket.io' );

module.exports.init = function(server){

 /**
     * Hi This is where things, get tricky now.
     * statement of Problem: Am trying to send message between two namespaces.
     * first made individual namespace socket global,
     * And create a function that will utilized these global sockets as their second arguments
     * and make calls to them
     */

io = io.listen( server );
var chatSystemPresentSocket; // making it Global
var chatUserPresentSocket;  //making it Global

io.of( '/chatSystem' ).on( 'connection', function( socket ) {
    /*handling set nickname event*/
    socket.on( 'set.name', function( data ) {
        /*attach nickname key to this socket*/
        //socket Global for the moment.
        chatSystemPresentSocket = socket;

        sendtochatSystem(data) // function calls
        socket.nickname = data.name;
        socket.broadcast.emit( 'user.entered', data );
    });
});

io.of( '/chatUser').on( 'connection', function( socket ) {
    /*handling client event socket.send*/
    socket.on( 'message', function( data ) {
        /* make socket global for the moment.*/
        chatUserPresentSocket = socket;
        sendtochatSystem(data);
        data = JSON.parse( data );
        data.nickname = socket.nickname; // <--- this is undefined

        /*send to all connected client( broadcast will not send message to socket that created the message)*/
        socket.broadcast.send( JSON.stringify( data ) );
        data.type = 'myMessage';

        /*manually send back the message to the socket that created the message*/
        socket.send( JSON.stringify( data) );
    });
});

//Make a function to use one of the global sockets of one of the namespaces
function sendToChatUser(data, chatUserPresentSocket){
chatUserPresentSocket.emit('your event', data)
}

function sendToChatSystem(data, chatSystemPresentSocket){
chatSystemPresentSocket.emit('your event', data)
}

};

测试它,如果它不适合你知道,在我的代码中编辑