【转载】Node.js + WebSocket 实现的简易聊天室
2012-11-01 18:10
961 查看
Node.js + WebSocket 实现的简易聊天室
本实例程序在Windows下测试通过。上述实例支持以下浏览器:
Firefox 7-9 (Old) (Protocol Version 8)
Firefox 10+ (Protocol Version 13)
Chrome 14,15 (Old) (Protocol Version 8)
Chrome 16+ (Protocol Version 13)
Internet Explorer 10 (Preview) (Protocol Version 13)
消息的传递也比较简单,Client –> Server, Server –> Client
服务器广播消息
数据传输使用的是JSON格式,前台建立连接的代码比较简单,ex:
$(function () {
window.WebSocket = window.WebSocket || window.MozWebSocket;
var connection = new WebSocket('ws://127.0.0.1:1337');
connection.onopen = function () {
//已建立连接
};
connection.onerror = function (error) {
//接收或发送消息时遇到了错误
};
connection.onmessage = function (message) {
try {
var json = JSON.parse(message.data);
} catch (e) {
console.log('不能被正常解析的数据:', message.data);
return;
}
// todo
};
});后端的实现,直接使用别人写好的模块所以传统比较简单一点(想在Windows下运行chat-server还是有点麻烦的),因为该模块在Windows下安装时,需要Microsoft Visual C++和Python 2.7的支持。--如果没有安装这两个东东,还得先安装一下。
如果顺利的话,会看到如下图所示的界面:
这样我们就可以创建Server了,实现的代码也并不复杂:
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(8080, function() {
console.log((new Date()) + ' Server is listening on port 8080');
});
wsServer = new WebSocketServer({
httpServer: server,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser.You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: false
});
function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
return true;
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept('echo-protocol', request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});从上述的例子中可以看出,websocket支持两种传递方式:二进制流、utf8的文本流。前面的例子中所使用的是utf8文本流
完整的chat-server.js的代码如下:
// http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
"use strict";
// Optional. You will see this name in eg. 'ps' or 'top' command
process.title = 'node-chat';
//websocket服务器监听的端口
var webSocketsServerPort = 1337;
var webSocketServer = require('websocket').server;
var http = require('http');
//保存最近100条消息记录
var history = [ ];
//当前连接的客户端
var clients = [ ];
/**
* 对聊天内容进行字符转义
*/
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}
var colors = [ 'red', 'green', 'blue', 'magenta', 'purple', 'plum', 'orange' ];
colors.sort(function(a,b) { return Math.random() > 0.5;} );
/**
* HTTP server
*/
var server = http.createServer(function(request, response) {});
server.listen(webSocketsServerPort, function() {
console.log(getNow() + " WebSocket Server is listening on port:" + webSocketsServerPort);
});
/**
* WebSocket server
* WebSocket server is tied to a HTTP server. To be honest I don't understand why.
*/
var wsServer = new webSocketServer({
httpServer: server
});
//每一个客户端请求建立连接时,都将触发此方法
wsServer.on('request', function(request) {
console.log(getNow() + ' ' + request.origin + ' 请求连接.');
// accept connection - you should check 'request.origin' to make sure that client is connecting from your website
// (http://en.wikipedia.org/wiki/Same_origin_policy)
var connection = request.accept(null, request.origin);
//保存当前请求连接客户端的索引,以方便在断开连接时,从连接池中移除该连接
var index = clients.push(connection) - 1;
var userName;
var userColor;
console.log(getNow() + ' 已建立连接...');
//推送历史聊天记录
if (history.length > 0) {
connection.sendUTF(JSON.stringify({type: 'history', data: history}));
}
//某一客户端发送消息过来
connection.on('message', function(message) {
if (message.type === 'utf8') {
//第一次请求用于保存用户信息
if (!userName) {
userName = htmlEntities(message.utf8Data);
userColor = colors.shift();
connection.sendUTF(JSON.stringify({ type:'color', data: userColor}));
console.log(getNow() + ' 用户已登录: ' + userName + ' -- ' + userColor);
} else {
//记录消息并广播
console.log(getNow() + userName + '-说: ' + message.utf8Data);
//传递给客户端的数据格式
var obj = {
time: (new Date()).getTime(),
text: htmlEntities(message.utf8Data),
author: userName,
color: userColor
};
history.push(obj);
//取数组最后100条消息记录并保存
history = history.slice(-100);
//将消息广播给所有客户端
var json = JSON.stringify({ type:'message', data: obj});
for (var i=0; i < clients.length; i++) {
clients[i].sendUTF(json);
}
console.log("总的客户端连接数:" + clients.length);
}
}
});
//用户断开连接
connection.on('close', function(connection) {
if (!userName && !userColor) {
console.log(getNow() + " -- " + connection.remoteAddress + " 断开链接.");
//从连接池中移除连接
clients.splice(index, 1);
//回收访用户所使用的颜色
colors.push(userColor);
}
});
});
function getNow() {
return new Date().format('yyyy-MM-dd hh:mm:ss');
}
Date.prototype.format = function (fmt) { //author: meizz
var o = {
"M+": this.getMonth() + 1,
"d+": this.getDate(),
"h+": this.getHours(),
"m+": this.getMinutes(),
"s+": this.getSeconds(),
"q+": Math.floor((this.getMonth() + 3) / 3),
"S": this.getMilliseconds()
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}运行supervisor chat-server.js或者node chat-server.js 就OK了~
使用Firefox测试一下:)
本文参考:
1、Node.js & WebSocket - Simple chat tutorial
2、WebSocket-Node
分类: Node.js
相关文章推荐
- Node.js + WebSocket 实现的简易聊天室
- node.js+websocket实现简易聊天室
- Node.js websocket 使用 socket.io库实现实时聊天室
- 实现使用Websocket通讯的聊天室——Node.js摸石头系列之六
- [转载]WebSocket+Node.js 通讯及在 iPhone中 实现
- HTML+CSS+JS+node.js实现websocket聊天室
- Node.js websocket使用socket.io库实现实时聊天室
- websocket+node.js实现实时聊天系统问题咨询
- node.js任务队列简易版实现(基于Promise)
- Node.js websocket 聊天室 相关资料
- 网页中实时查看服务器日志(websocket + node.js实现)
- 使用Node.js实现简易MVC框架
- 基于WebSocet简单聊天室(NodeJS + node-websocket-server)
- 我的小工具-远程读卡器web客户端(nodejs+websocket实现实时指令交互)
- Node.js实现的简易网页抓取功能示例
- AngularJS+Node.js实现在线聊天室
- node.js之websocket协议的实现
- WebSocket实现简易聊天室
- 基于Node.js的WebSocket通信实现
- Node.js+Socket.IO实现的WebSocket群聊天室源码