0

我正在尝试构建一个没有 socket.io 的简单 tcp 聊天服务器。现在,我可以通过连接到服务器的所有套接字广播数据。

我的问题是为每个连接分配一个套接字标识符并从一个对象中检索它们。

这是代码:

var net = require('net');

//keep track of sockets
var allSockets = {
  sockets: {},
  addSocket: function(socket, nick, table) {
    this.sockets[table+nick] = socket;
  },
  removeSocket: function(nick, table) {
    if (this.sockets[table+nick] !== undefined) {
      this.sockets[table+nick] = null;
      delete this.sockets[table+nick];
    }
  }
};

// create the server
var server = net.createServer(function (socket) {
  var connected = false;
  var jsoncommand = true;

  //first data sent MUST BE json formatted string in this format 
  //{"nick":"someid","table":"tablenumber"}

  var thisnick = "";
  var thistable = "";

  // get client ip
  socket.name = socket.remoteAddress;

  //write something on each connect
  socket.write("You are connecting from " + socket.name + "\n");
  socket.write(socket.name + " joined chat\n");

  //handle data streams
  socket.on('data', function (data) {
    if (jsoncommand) {
      //JSON.parse the first data stream
      var some = JSON.parse(data);

      //assign a socket.id based on nick and table
      allSockets.addSocket(socket, some.table, some.nick);

      socket.write(some.nick + " joined " + some.table + "\n");
      thisnick = some.nick;
      thistable = some.table;

      connected = true;

      //no longer waiting for first stream as JSON
      jsoncommand = false;
    } else if (connected) {
      //write whatever data it recieves (function is below)
      broadcast(data, thistable);
    } else {
      socket.write("You are not connected to any table");
      socket.destroy();
      connected = false;
      jsoncommand = true;
      thisnick = "";
      thistable = "";
    }
  });

  // remove the socket from allSockets but broadcast 
  //only to other users on the same table
  socket.on('end', function () {
    allSockets.removeSocket(thisnick, thistable);
    broadcast(thisnick + " has left table " + thistable, thistable);
  });

  //this function should select from the allSockets object, 
  //only those, whose property matches "table"
  //and write to those sockets only, when called

  function broadcast(message, table) {
    allSockets.sockets.forEach(function(socket) {
      if (socket.hasOwnProperty(table)) {
        socket.write(message);
      }
    });
  }
});

server.listen(8000);
console.log("running at port 8000\n");

只需将其部署在您的机器上并使用 nc 连接到端口 8000 并确保您发送的第一件事是 {"nick":"mynick","table":"mytable"} 您将看到一条消息,您的尼克加入了你的餐桌。

现在,如果您向它发送其他内容,基于它存储了您的表名这一事实,它应该回显您发送的任何内容,发送给您和其他具有不同昵称但在同一张表上的连接,但服务器死机,抛出错误allSockets 对象没有“for”或“forEach”方法或 indexOf 或任何其他方法。

那么,我该如何纠正呢?

如果我的昵称是“john”并且我加入了“my_table”,并且“mary”、“lisa”和“ana”也加入了同一个“my_table”,假设我不知道他们的昵称,但我知道他们在“my_table”,我如何从 allSockets 对象中选择那些包含“my_table”的套接字。

我尝试了 hasOwnProperty,但它返回布尔值,它只告诉我有具有该属性的套接字,但是我如何将它们放入 for 或 foreach 循环中以便写入它们。

我知道这可能是一个愚蠢的问题,或者我什至没有正确地解决这个问题,但我是一个 node.js 初学者,所以任何建议都非常受欢迎。

顺便说一句,我将这些来自网络上的示例放在一起。

至于 JSON 字符串,它首先由桌面应用程序在连接时发送。无论如何,我选择它是出于测试目的,所以不要理会它。

4

1 回答 1

0

我想关于 forEach 的错误发生在这里:

allSockets.sockets.forEach(function(socket) {

虽然 allSockets.sockets 不是 Array,但它是对象(key > value 模型,如哈希表)。

因此,要遍历其中的每个套接字,您应该将循环更改为:

for(var key in allSockets.sockets) {
  var socket = allSockets.sockets[key];
  // your logic here
}
于 2012-12-20T14:50:10.427 回答