From b1c444883f4c7b5ad66c347365f39a15c909dccf Mon Sep 17 00:00:00 2001 From: Paul Querna Date: Mon, 13 Dec 2010 23:27:40 -0800 Subject: [PATCH] Add basic chat client & server --- udp/chat-client.js | 24 ++++++++++++++++ udp/chat-server.js | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 udp/chat-client.js create mode 100644 udp/chat-server.js diff --git a/udp/chat-client.js b/udp/chat-client.js new file mode 100644 index 0000000..8e0bb7f --- /dev/null +++ b/udp/chat-client.js @@ -0,0 +1,24 @@ +/* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying + * LICENSE file. + */ + +var Buffer = require('buffer').Buffer; +var dgram = require('dgram'); + +var stdin = process.openStdin(); +stdin.setEncoding('utf8'); + +SERVER_HOST = '127.0.0.1'; +SERVER_PORT = 7000; + +var sock = dgram.createSocket("udp4"); + +stdin.on('data', function (input) { + var buf = new Buffer(input); + sock.send(buf, 0, buf.length, SERVER_PORT, SERVER_HOST); +}); + +sock.on('message', function (buf) { + process.stdout.write(buf.toString()); +}); diff --git a/udp/chat-server.js b/udp/chat-server.js new file mode 100644 index 0000000..b98eb1e --- /dev/null +++ b/udp/chat-server.js @@ -0,0 +1,72 @@ +/* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying + * LICENSE file. + */ + +var Buffer = require('buffer').Buffer; +var dgram = require('dgram'); +var log = require('sys').log; +var CLIENT_GENERATION_GAP = 10; +var CLIENT_CLEANER_INTERVAL = 1000; +SERVER_HOST = '127.0.0.1'; +SERVER_PORT = 7000; + +function ts() { + return Math.round(new Date().getTime() / 1000); +} + +var clients = {}; +var generation = ts(); +var sock = null; + +var si = setInterval(function() { + generation = ts(); + for (var ckey in clients) { + if (clients.hasOwnProperty(ckey)) { + var gap = generation - clients[ckey]; + /* No ping from this client in X seconds, assume its dead. */ + if (gap > CLIENT_GENERATION_GAP) { + delete clients[ckey]; + } + } + } +}, CLIENT_CLEANER_INTERVAL); + +function updateTimeout(key) { + clients[key] = generation; +} + +function broadcast(buf) { + var c = 0; + for (var ckey in clients) { + if (clients.hasOwnProperty(ckey)) { + var host = ckey.slice(0, ckey.lastIndexOf(':')); + var port = parseInt(ckey.slice(ckey.lastIndexOf(':')+1), 10); + c++; + sock.send(buf, 0, buf.length, port, host); + } + } + log('Broadcasted to '+ c + ' clients'); +} + +function processMsg(msg, peer) { + var str = msg.toString(); + str = str.replace(/[\n\r]/g, ""); + if (str.length > 0) { + var buf = new Buffer(peer.address + ":"+ peer.port + "> "+ str + '\n'); + broadcast(buf); + } +} + +sock = dgram.createSocket("udp4", function (msg, peer) { + var key = peer.address + ":" + peer.port; + log('got message'); + updateTimeout(key); + processMsg(msg, peer); +}); + +sock.on('listening', function() { + log('Bound to '+ SERVER_HOST + ':' + SERVER_PORT); +}); +sock.bind(SERVER_PORT, SERVER_HOST); +