简体   繁体   中英

node.js simple tcp chat server

I am trying to build a simple tcp chat server, WITHOUT socket.io. Now, I have no problem broadcasting data across all sockets connected to the server.

My problem is assigning a socket identifier to each connection and retrieving them from an object.

Here is the code:

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");

Just deploy this on your machine and connect with nc to port 8000 and be sure that the first thing you send it is something like {"nick":"mynick","table":"mytable"} you will see a message that your nick joined your table.

now if you send it something else, based on the fact that it stored your table name, it should echo whatever you send it, to you and to other connections with different nicks but on the same table, but the server dies, throwing an error that the allSockets object, does not have a "for" or "forEach" method or indexOf, or any other.

SO, how do I correct this?

If my nick is "john" and I joined "my_table", and also "mary", "lisa" and "ana" joine the same "my_table", assuming I don't know their nicks, but I do know they are on "my_table", HOW do I select from the allSockets object, those sockets that contain "my_table".

I tried hasOwnProperty, but that returns boolean, which only tells me that there are sockets with that property, but how do I put them in a for, or foreach loop in order to write to them.

I know it may be a silly question, or maybe im not even aproaching this correctly, but im a node.js beginner, so any advice is greatly apreaciated.

By the way I put this together from examples across the web.

As for the JSON string, its the first thing being sentby a desktop app on connection. Anyways I chose it for testing purposes so don't bother with it.

I suppose error about forEach happens here:

allSockets.sockets.forEach(function(socket) {

While allSockets.sockets is not Array, but it is object (key > value model, like hash table).

So to loop through each socket in it, you should change loop to:

for(var key in allSockets.sockets) {
  var socket = allSockets.sockets[key];
  // your logic here
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM