Created
October 22, 2012 17:55
-
-
Save Cacodaimon/3932968 to your computer and use it in GitHub Desktop.
WebSocket nodejs server & client tutorial used @ cacodaemon.de
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports.Client = function (name, socket) { | |
this.name = name | |
this.socket = socket | |
this.send = function (msg) { | |
this.socket.send(msg) | |
} | |
this.toString = function (msg) { | |
return this.name | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Client = require('./client.js').Client | |
module.exports.Clients = function () { | |
var clients = new Array() | |
var clientCounter = 0 | |
this.sendToClient = function (client, msg) { | |
try { | |
client.send(msg) | |
} | |
catch (error) { | |
console.log(error) | |
if (error == 'Error: not opened') { | |
this.removeClient(null, client.name) | |
} | |
} | |
} | |
this.forEachClient = function (callBack) { | |
for (var i = clients.length - 1; i >= 0; i--) { | |
if (!clients[i]) { | |
clients.splice(i, 1) | |
continue | |
} | |
callBack(clients[i], i) | |
} | |
} | |
this.getClientByName = function (name) { | |
for (var i = clients.length - 1; i >= 0; i--) { | |
if (clients[i].name == name) { | |
return clients[i] | |
} | |
} | |
return null | |
} | |
this.getClientBySocket = function (socket) { | |
for (var i = clients.length - 1; i >= 0; i--) { | |
if (clients[i].socket == socket) { | |
return clients[i] | |
} | |
} | |
return null | |
} | |
this.addClient = function (socket) { | |
var client = new Client('User_' + ++clientCounter, socket) | |
clients.push(client) | |
this.sendToClient(client, '/welcome ' + client) | |
this.sendToAll('/users ' + clients.join(' ')) | |
return client | |
} | |
this.removeClient = function (socket, name) { | |
var removedClients = new Array() | |
for (var i = clients.length - 1; i >= 0; i--) { | |
if (socket && clients[i].socket == socket) { | |
removedClients.push(clients[i]) | |
clients.splice(i, 1) | |
} | |
if (name && clients[i].name == name) { | |
removedClients.push(clients[i]) | |
clients.splice(i, 1) | |
} | |
} | |
for (var i = removedClients.length - 1; i >= 0; i--) { | |
this.sendToAll('/removed ' + removedClients[i]) | |
} | |
} | |
this.sendToAll = function (msg) { | |
var thath = this | |
this.forEachClient(function (client, i) { | |
thath.sendToClient(client, msg) | |
}) | |
} | |
this.sendToAllFromClient = function (msg, socket) { | |
var sender = this.getClientBySocket(socket) | |
var thath = this | |
this.forEachClient(function (client, i) { | |
if (sender == client) { | |
return | |
} | |
thath.sendToClient(client, sender + ': ' + msg) | |
}) | |
} | |
this.command = function (msg, socket) { | |
if (msg.substr(0, 1) != '/') { | |
return false | |
} | |
var client = this.getClientBySocket(socket) | |
var params = msg.split(' ') | |
var type = params[0] | |
params.splice(0, 1) | |
switch (type) { | |
case '/name': | |
if (!params[0]) { | |
return false | |
} | |
var oldName = client.name | |
client.name = params[0] | |
this.sendToAll('/name_change ' + oldName + ' ' + client.name) | |
break | |
case '/private': | |
if (params.length < 2) { | |
return false | |
} | |
var reciever = this.getClientByName(params[0]) | |
params.splice(0, 1) | |
var privateMsg = '/private ' + client.name + ': ' + params.join(' ') | |
this.sendToClient(reciever, privateMsg) | |
this.sendToClient(client, privateMsg) | |
break | |
} | |
return true | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<title>Caco's Websocket Chat</title> | |
<link rel="stylesheet" href="screen.css" /> | |
</head> | |
<body> | |
<header class="center"> | |
<hgroup> | |
<h1>Caco's Websocket Chat</h1> | |
</hgroup> | |
</header> | |
<nav> | |
</nav> | |
<div class="center"> | |
<section id="chat"> | |
<ul id="chat_area"></ul> | |
<form id="char_form"> | |
<fieldset> | |
<input type="text" name="chat_input" value="" id="chat_input"/> | |
</fieldset> | |
</form> | |
</section> | |
<section id="users"> | |
<ul id="users_area"></ul> | |
</section> | |
</div> | |
<footer class="center"> | |
<p>A tutorial by <a href="http://www.cacodaemon.de">Cacodaemon</a></p> | |
</footer> | |
</body> | |
<script type="text/javascript" src="websocket-client.js"></script> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.center { | |
margin-left: auto; | |
margin-right: auto; | |
width: 800px | |
} | |
ul { | |
margin: 0; | |
padding: 0; | |
list-style-type: none | |
} | |
fieldset { | |
border: 0 | |
} | |
input { | |
border: 1px solid black; | |
width: 100% | |
} | |
footer { | |
clear: both | |
} | |
#chat { | |
width: 600px; | |
float: left | |
} | |
#users { | |
width: 200px; | |
float: left | |
} | |
#chat_area { | |
height: 200px; | |
overflow-y: scroll | |
} | |
#users_area { | |
height: 200px | |
} | |
.public { | |
background-color: #B5D045 | |
} | |
.private { | |
background-color: #F47E7D | |
} | |
.own { | |
background-color: #66CCCC | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function $ (elementId) { return document.getElementById(elementId) } | |
var webSocket = new WebSocket('ws://localhost:1337') | |
var chatArea = $('chat_area') | |
var chatForm = $('char_form') | |
var chatInput = $('chat_input') | |
var usersArea = $('users_area') | |
var messageCounter = 0 | |
var myName = null | |
function addMessage (msg, type) { | |
var newMessage = document.createElement('li') | |
newMessage.textContent = newMessage.innerText = msg | |
newMessage.setAttribute('id', 'msg_' + messageCounter) | |
newMessage.setAttribute('class', type) | |
chatArea.appendChild(newMessage) | |
chatArea.scrollTop = chatArea.scrollHeight | |
if (messageCounter > 20) { | |
oldMessage = $('msg_' + (messageCounter - 21)) | |
chatArea.removeChild(oldMessage) | |
} | |
messageCounter++ | |
} | |
function addUser (users) { | |
for (var i = users.length - 1; i >= 0; i--) { | |
var userName = users[i] | |
if ($('user_' + userName)) { | |
continue | |
} | |
var newUser = document.createElement('li') | |
newUser.textContent = newUser.innerText = userName | |
newUser.setAttribute('id', 'user_' + userName) | |
if (myName == userName) { | |
newUser.setAttribute('class', 'own') | |
} | |
newUser.onclick = function () { | |
if (this.getAttribute('class') == 'own') { | |
webSocket.send('/name ' + prompt('Enter new nick name: ', myName)) | |
} | |
else { | |
webSocket.send('/private ' + this.innerText + ' ' + prompt('Enter private message to: ' + this.innerText, '')) | |
} | |
} | |
usersArea.appendChild(newUser) | |
} | |
} | |
function changeUserName (from, to) { | |
var user = $('user_' + from); | |
user.textContent = user.innerText = to | |
user.setAttribute('id', 'user_' + to) | |
if (from == myName) { | |
myName = to | |
} | |
} | |
function removeUser (userName) { | |
usersArea.removeChild($('user_' + userName)) | |
} | |
function privateMessage (message) { | |
addMessage(message, 'private') | |
} | |
function command(msg) { | |
if (msg.substr(0, 1) != '/') { | |
return false | |
} | |
var params = msg.split(' ') | |
var type = params[0] | |
params.splice(0, 1) | |
switch (type) { | |
case '/users': | |
addUser(params) | |
break | |
case '/name_change': | |
changeUserName(params[0], params[1]) | |
break | |
case '/removed': | |
removeUser(params) | |
break | |
case '/private': | |
privateMessage(params.join(' ')) | |
break | |
case '/welcome': | |
myName = params[0] | |
break | |
} | |
return true | |
} | |
webSocket.onmessage = function (msg) { | |
if (command(msg.data)) { | |
return | |
} | |
addMessage(msg.data, 'public') | |
} | |
chatForm.onsubmit = function(form) { | |
if (chatInput.value == '') { | |
return false | |
} | |
webSocket.send(chatInput.value) | |
addMessage(chatInput.value, 'own') | |
chatInput.value = '' | |
return false | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var WebSocketServer = new require('ws').Server | |
var webSocketServer = new WebSocketServer({port: 1337}) | |
var Clients = new require('./clients.js').Clients | |
var clients = new Clients() | |
webSocketServer.on('connection', function(webSocket) { | |
console.log('new connection') | |
clients.addClient(webSocket) | |
webSocket.on('message', function(msg) { | |
console.log('incomming msg from: ' + clients.getClientBySocket(webSocket) + ' (' + msg + ')') | |
if (clients.command(msg, webSocket)) { | |
return | |
} | |
clients.sendToAllFromClient(msg, webSocket) | |
}) | |
webSocket.on('close', function() { | |
console.log('closed connection') | |
}) | |
}) | |
var http = require('http'); | |
var fs = require('fs'); | |
var mime = new Array() | |
mime.css = 'text/css' | |
mime.html = 'text/html' | |
mime.js = 'text/javascript' | |
http.createServer(function (req, res) { | |
if (req.url == '/') { | |
req.url = '/index.html' | |
} | |
var fileType = req.url.split('.')[1] | |
console.log(mime[fileType]) | |
fs.readFile('Client/' + req.url, function (err, data) { | |
if (err) { | |
res.writeHead(404, {'Content-Type': 'text/html'}); | |
res.end('<h1>404</h1><h2>File: ' + req.url + ' not found!</h2>'); | |
} | |
else if (data) { | |
res.writeHead(200, {'Content-Type': mime[fileType]}); | |
res.end(data); | |
} | |
}); | |
}).listen(8080, '127.0.0.1'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment