Created
September 25, 2012 14:21
-
-
Save simonkcleung/3782229 to your computer and use it in GitHub Desktop.
node.js websocket example
This file contains 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 server=require('websocket.js').createServer(); | |
var chatroom=server.addApp('/chatroom'); | |
chatroom.ondata=function(data,userName){ | |
this.broadcast(data,userName); | |
} | |
chatroom.onclose=function(userName){ | |
this.broadcast(userName+" disconnected."); | |
} | |
chatroom.onconnect=function(userName){ | |
this.broadcast(userName+" connected."); | |
} | |
server.listen(8080); |
This file contains 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
<!docytpe html> | |
<html> | |
<head> | |
<meta charset="UTF-8" /> | |
<title>web socket</title> | |
<style> | |
#userinput,#userid{ | |
width:435px; | |
} | |
button{ | |
min-width:60px; | |
} | |
#disconnectBtn{ | |
display:none; | |
} | |
#chatbox{ | |
height:20em; | |
width:500px; | |
} | |
</style> | |
<script> | |
"use strict"; | |
var ws,userName,send,userinput,disconnectBtn,chatbox; | |
window.onload=function(){ | |
var $=document.getElementById.bind(document); | |
send=$('send'); | |
userinput=$('userinput'); | |
disconnectBtn=$('disconnectBtn'); | |
chatbox=$('chatbox'); | |
} | |
function disconnect(){ | |
ws.close(); | |
send.textContent='connect'; | |
userinput.value=userName; | |
disconnectBtn.style.display=''; | |
chatbox.value+='disconnecting...\n'; | |
} | |
function sendmsg(){ | |
if (!ws || ws.readyState===3){ | |
if (userinput.value){ | |
userName=userinput.value; | |
ws=new WebSocket("ws://localhost:8080/chatroom?user="+userName); | |
ws.onopen=function(){ | |
chatbox.value+='connected>\n'; | |
send.textContent='send'; | |
userinput.placeholder='Message'; | |
userinput.value=''; | |
disconnectBtn.style.display='inline-block'; | |
}; | |
ws.onmessage=function(evt){chatbox.value+=evt.data+'\n'}; | |
ws.onerror=function(){chatbox.value+='error>\n'}; | |
ws.onclose=function(){ | |
chatbox.value+='disconnected>\n'; | |
send.textContent='connect'; | |
userinput.value=userName; | |
userinput.placeholder='User Name'; | |
disconnectBtn.style.display=''; | |
}; | |
} | |
} else if (ws.readyState===1){ | |
ws.send(userinput.value); | |
userinput.value=''; | |
} | |
} | |
</script> | |
</head> | |
<body> | |
<textarea id="chatbox"></textarea><br/> | |
<input id="userinput" placeholder="User Name"></input> | |
<button id="send" onclick="sendmsg()">connect</button> | |
<br/> | |
<button id="disconnectBtn" onclick="disconnect()">disconnect</button> | |
<button onclick="chatbox.value+=['CONNECTING','OPEN','CLOSING','CLOSED'][ws.readyState]+'>\n'">connection state</button> | |
<button onclick="chatbox.value=''">clear</button> | |
</body> | |
</html> |
This file contains 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 http=require('http'), crypto=require('crypto'), urlparser=require('url').parse | |
,HandshakeResponseHead="HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " | |
,GUI="258EAFA5-E914-47DA-95CA-C5AB0DC85B11", CLOSE_BUFFER=new Buffer([136,2,3,232]) | |
,BUFFERLEN7BITS=new Buffer(2), BUFFERLEN16BITS=new Buffer(4); | |
BUFFERLEN7BITS[0]=BUFFERLEN16BITS[0]=129; | |
BUFFERLEN16BITS[1]=126; | |
module.exports.createServer=function(s){ | |
if (s instanceof http.Server==false) s=http.createServer(); | |
s.on('upgrade',handShake); | |
s.apps=new Object; | |
s.addApp=addApp; | |
return s; | |
} | |
function handShake(request,socket){ | |
var header=request.headers,url=urlparser(request.url,true), key; | |
if (request.method!="GET") return rejectConnection(405,socket); | |
if (parseFloat(request.httpVersion)<1.1) return rejectConnection(505,socket); | |
if (url.pathname in this.apps==false) return rejectConnection(404,socket); | |
if (parseInt(header['sec-websocket-version'],10)<13) return rejectConnection(426,socket); | |
if (header.upgrade!="websocket") return rejectConnection(406,socket); | |
key=header['sec-websocket-key']; | |
if (key){ | |
socket.write(HandshakeResponseHead+crypto.createHash('sha1').update(key+GUI).digest('base64')+ "\r\n\r\n",'ascii'); | |
this.apps[url.pathname].addConnection(socket,url.query.user); | |
} else rejectConnection(417,socket); | |
} | |
function rejectConnection(statusCode,socket){ | |
socket.end('HTTP/1.1 '+statusCode+' '+http.STATUS_CODES[statusCode]+'\r\n\r\n','ascii'); | |
} | |
function addApp(url){ | |
this.apps[url]=new Application(url); | |
return this.apps[url]; | |
} | |
function Application(url){ | |
this.connections=new Object; | |
} | |
Application.prototype.addConnection=function(socket,userName){ | |
if (userName in this.connections == false) | |
this.connections[userName]=new Connection(socket,userName,this); | |
} | |
Application.prototype.close=function(userName){ | |
var c=this.connections, s; | |
if (userName in c){ | |
s=c[userName].socket; | |
s.end(CLOSE_BUFFER); | |
s.removeAllListeners(); | |
s.destroy(); | |
delete c[userName]; | |
if (this.onclose) this.onclose(userName); | |
} | |
} | |
Application.prototype.broadcast=function(buffer,userName){ | |
if (typeof buffer =='string') buffer=new Buffer(buffer); | |
var len=buffer.length, bufferhead, c=this.connections, user , s; | |
if (userName) { | |
userName=new Buffer(userName+': '); | |
len+=userName.length; | |
} | |
if (len<126){ | |
bufferhead=BUFFERLEN7BITS; | |
bufferhead[1]=len; | |
} else if (len<65536){ | |
headbuffer=BUFFERLEN16BITS; | |
headbuffer.writeUInt16BE(len,2); | |
} else return ; | |
for (user in c){ | |
s=c[user].socket; | |
s.write(bufferhead); | |
if (userName) s.write(userName); | |
s.write(buffer); | |
} | |
} | |
function Connection(socket,userName,app){ | |
function onData(buffer){ | |
var i=2, j, opcode=buffer[0]&15, length=buffer[1]&127; | |
if (length==127 || opcode==8) return app.close(userName); | |
if (opcode==1){ | |
if (length==126){ | |
length=buffer.readUInt16BE(2); | |
i+=2; | |
} | |
var maskingKeys=buffer.slice(i,i+=4), payloadData=buffer.slice(i); | |
for (j=0;j<4;j++) | |
for (i=j, maskingKey=maskingKeys[j];i<length;i+=4) | |
payloadData[i]^=maskingKey; | |
if (app.ondata) app.ondata(payloadData,userName); | |
} | |
} | |
socket.on('data',onData); | |
this.socket=socket; | |
if (app.onconnect) app.onconnect(userName); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment