Skip to content

Instantly share code, notes, and snippets.

@mattrasband
Last active December 30, 2015 10:39
Show Gist options
  • Save mattrasband/7817596 to your computer and use it in GitHub Desktop.
Save mattrasband/7817596 to your computer and use it in GitHub Desktop.
A basic chat server written in Node.js. Tried to improve on the ones that are currently floating around. Note: Not great from telnet on Windows - works fine on *nix.
/*
File: ChatServer.js
Author: Nerdwaller
Description:
A fairly simple chat server using Node.js.
It takes several pieces from other scripts, adds some original pieces, and additional functionality.
*/
var net = require("net");
// Server Config
var SERVER = {
name : "Node.js Simple Chat Server",
port : 8000,
host : "127.0.0.1",
prmpt: "> "
};
// Class For Client Sockets
function Socket(socket) {
this.uname = null; // Username
this.id = null; // Unique ID (IP:PORT)
this.socket = socket; // Socket Object
this.buffer = ""; // Buffer of Text
}
// Proto for removing items from arrays.
Array.prototype.remove = function(e) {
for (var i = 0; i < this.length; i++) {
if (e == this[i]) {
return this.splice(i, 1);
}
}
};
// Proto to check for an object in the array (Searches by member variable)
Array.prototype.exists = function(attrib, value) {
var found = false;
this.forEach(function(c) {
if (c.hasOwnProperty(attrib) && c[attrib] == value) {
found = true;
}
});
return found;
};
// List of connected clients
var CLIENTS = [];
// Create the server and add listeners for events.
var srv = net.createServer(function(socket) {
// CTOR (Client Connect)
var client = new Socket(socket);
CLIENTS.push(client);
socket.setEncoding("utf8");
client.id = socket.remoteAddress + ':' + socket.remotePort;
client.uname = client.id; // Set a default username
// Report to the server and other clients that someone has connected.
console.log("+" + client.id + ", " + CLIENTS.length + " connected clients.");
socket.write("Welcome to " + SERVER.name + ".\r\n");
socket.write(SERVER.prmpt);
CLIENTS.forEach(function(c) {
if (c != client) {
c.socket.write("\r<srv>: " + client.id + " has joined.\r\n");
c.socket.write(SERVER.prmpt);
}
});
// DTOR (Client Disconnect)
socket.addListener('end', function() {
CLIENTS.remove(client);
console.log("-" + client.id + ", " + CLIENTS.length + " connected clients.");
CLIENTS.forEach(function(c) {
c.socket.write(client.id + " has left.\r\n");
c.socket.write(SERVER.prmpt);
});
socket.end();
});
// Handle Received Data
socket.addListener("data", function(d) {
client.buffer += d;
if (client.buffer[client.buffer.length - 1] == "\n") {
if (client.buffer.match(/^!.*/)) { // A command always takes form !command
var cmd = client.buffer.split(" ")[0];
var params = client.buffer.split(" ");
cmd = cmd.replace("!", "").trim();
switch(cmd) {
case "quit":
client.socket.end();
return;
case "set":
switch(params[1]) {
case "name":
if (!CLIENTS.exists("uname", params[2].trim())) {
client.uname = params[2].trim();
}
else {
client.socket.write("Username already taken.\r\n");
}
break;
default:
client.socket.write("Valid !set commands:\r\n\t!set name uname\r\n");
}
break;
default:
client.socket.write("Invalid command.\r\n");
}
}
else {
CLIENTS.forEach(function(c) {
if (c != client) {
c.socket.write("\r" + client.uname + ": " + client.buffer);
c.socket.write(SERVER.prmpt);
}
});
}
client.buffer = "";
client.socket.write(SERVER.prmpt);
}
});
// Interrupt Handlers
process.on('SIGINT', function() {
console.log("SIGINT detected, shutting down server and disconnecting all clients (" + CLIENTS.length + ").");
CLIENTS.forEach(function(c) {
c.socket.write("Server is shutting down, your connection will be closed.");
c.socket.end();
});
process.exit();
});
});
srv.listen(SERVER.port, SERVER.host);
console.log("Server is running on " + SERVER.host + ":" + SERVER.port);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment