如何连接到现有的套接字io连接

时间:2014-06-20 08:01:10

标签: node.js socket.io

我的应用程序以这种方式工作:

  1. 用户登录网站
  2. JavaScript连接到Socket.IO服务器,并传输PHPSESSID
  3. Socket.IO使用PHPSESSID连接数据库,然后获取user_id
  4. 使用user_id我们再次连接数据库以获取user_place
  5. 然后,用户可以连接到会议室user_place并可以与其他人交谈
  6. 问题是user_place可以通过,例如,另一个PHP脚本进行更改。

    所以当它发生变化时,我需要告诉当前socket io连接从数据库中获取新的“user_place”,这样它就可以离开当前的房间并连接到新房间。

    我怎样才能做到这一点?

    我猜了两次:

    1. 执行php脚本时,连接到现有的Socket.IO连接并执行client.on('update_place'), function() {}之类的代码。 问题是我不知道如何连接到现有连接(是否可能?)
    2. 如果“user_place”发生了变化,那么有一个setTimeout()函数在数据库上进行常量检查(但是,这会很糟糕)
    3. 以下是节点服务器的一些简化代码:

      io.sockets.on('connection', function(client) {
      
          var user_place;
      
          // Read client cookies
          if(client.handshake.headers['cookie']) {
              var cookies = cookie.parse(client.handshake.headers['cookie']);
          }
      
          // If cookies exist, connect to database and get “user_place”
          if(cookies) {
              connection.query("SELECT session_value, session_time FROM sessions WHERE session_id = ?", [cookies.PHPSESSID], function(err, rows, fields) {
                  if(rows[0]) {
                      var session_value_json = JSON.parse(atob(rows[0].session_value));
                      user_id = session_value.user_id;
      
                      if(user_id) {
                          connection.query( "SELECT place FROM users WHERE id = ?", [user_id], function(err, rows, fields) {
      
                              // Set data user_place
                              user_place = rows[0].user_place;
      
                              // Join the room
                              client.join(user_place);
                          });
                      }
                  }
              });
          }
      
          // Chatting...
          client.on('message', function (data) {
              io.sockets.in(user_place).emit('message', {     
                  user_id         : user_id,
                  message_content : data.message
                  } 
              );  
          });
      });
      

1 个答案:

答案 0 :(得分:1)

我怀疑你可以从PHP连接到Socket.IO,但你可以采用另一种方式。

首先,创建一个对象,用于存储用户ID和套接字ID之间的关系:

var userSocketIds = {};
io.sockets.on('connection', function(client) {
    ...
        connection.query( "SELECT place FROM users WHERE id = ?", [user_id], function(err, rows, fields) {

            // Set data user_place
            user_place = rows[0].user_place;

            // Join the room
            client.join(user_place);

            userSocketIds[user_id] = client.id;
            client.on('disconnect', function() {
                delete userSocketIds[user_id];  //collect garbage
            });
        });
    ...
});

因此,如果您知道用户ID,则可以获得Socket.IO客户端ID,如下所示:

var clientId = userSocketIds[user_id];

然后,当更改user_place时,将POST请求发送到节点(例如,发送到http://127.0.0.1:1337/change_user_place)并将user_idnew_place参数传递给它。

在节点方面,您可以使用Express处理此类请求并更改用户的房间:

app.post('/change_user_place', function(req, res) {
    var clientId = userSocketIds[req.body.user_id];
    if (clientId && io.sockets.connected[clientId]) {
        io.sockets.connected[clientId].join(req.body.new_place);  //join user to new_place
    }
});

当然,您也可以发送GET请求而不是POST(并且更容易实施 - 您不需要安装body-parser中间件),但是如果操作改变了服务器端的某些内容,那么使用POST方法会更好。检查this

您也可以(并且应该)实施密码授权等操作。这很简单:您的PHP脚本只需传递一些密码以及用户ID和新位置,节点应验证此密码。

祝你好运,对不起我的英语。