Node.js + WebSocket 实现的简易聊天室

简介: 本实例程序在Windows下测试通过。 上述实例支持以下浏览器: Firefox 7-9 (Old) (Protocol Version 8) Firefox 10+ (Protocol Version 13) Chrome 14,15 (Old) (Protocol ...

本实例程序在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

node.js-chat-client-server.png

 

服务器广播消息

node.js-chat-server-client.png

 

 

数据传输使用的是JSON格式,前台建立连接的代码比较简单,ex:

   1: $(function () {
   2:     window.WebSocket = window.WebSocket || window.MozWebSocket;
   3:  
   4:     var connection = new WebSocket('ws://127.0.0.1:1337');
   5:  
   6:     connection.onopen = function () {
   7:         //已建立连接
   8:     };
   9:  
  10:     connection.onerror = function (error) {
  11:         //接收或发送消息时遇到了错误
  12:     };
  13:  
  14:     connection.onmessage = function (message) {
  15:         
  16:         try {
  17:             var json = JSON.parse(message.data);
  18:         } catch (e) {
  19:             console.log('不能被正常解析的数据:', message.data);
  20:             return;
  21:         }
  22:  
  23:         // todo
  24:     };
  25: });

后端的实现,直接使用别人写好的模块所以传统比较简单一点(想在Windows下运行chat-server还是有点麻烦的),因为该模块在Windows下安装时,需要Microsoft Visual C++和Python 2.7的支持。--如果没有安装这两个东东,还得先安装一下。

如果顺利的话,会看到如下图所示的界面:

这样我们就可以创建Server了,实现的代码也并不复杂:

   1: var WebSocketServer = require('websocket').server;
   2: var http = require('http');
   3:  
   4: var server = http.createServer(function(request, response) {
   5:     console.log((new Date()) + ' Received request for ' + request.url);
   6:     response.writeHead(404);
   7:     response.end();
   8: });
   9: server.listen(8080, function() {
  10:     console.log((new Date()) + ' Server is listening on port 8080');
  11: });
  12:  
  13: wsServer = new WebSocketServer({
  14:     httpServer: server,
  15:     // You should not use autoAcceptConnections for production
  16:     // applications, as it defeats all standard cross-origin protection
  17:     // facilities built into the protocol and the browser.  You should
  18:     // *always* verify the connection's origin and decide whether or not
  19:     // to accept it.
  20:     autoAcceptConnections: false
  21: });
  22:  
  23: function originIsAllowed(origin) {
  24:   // put logic here to detect whether the specified origin is allowed.
  25:   return true;
  26: }
  27:  
  28: wsServer.on('request', function(request) {
  29:     if (!originIsAllowed(request.origin)) {
  30:       // Make sure we only accept requests from an allowed origin
  31:       request.reject();
  32:       console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
  33:       return;
  34:     }
  35:  
  36:     var connection = request.accept('echo-protocol', request.origin);
  37:     console.log((new Date()) + ' Connection accepted.');
  38:     connection.on('message', function(message) {
  39:         if (message.type === 'utf8') {
  40:             console.log('Received Message: ' + message.utf8Data);
  41:             connection.sendUTF(message.utf8Data);
  42:         }
  43:         else if (message.type === 'binary') {
  44:             console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
  45:             connection.sendBytes(message.binaryData);
  46:         }
  47:     });
  48:     connection.on('close', function(reasonCode, description) {
  49:         console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
  50:     });
  51: });

从上述的例子中可以看出,websocket支持两种传递方式:二进制流、utf8的文本流。前面的例子中所使用的是utf8文本流

 

完整的chat-server.js的代码如下:

   1: // http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
   2: "use strict";
   3:  
   4: // Optional. You will see this name in eg. 'ps' or 'top' command
   5: process.title = 'node-chat';
   6:  
   7: //websocket服务器监听的端口
   8: var webSocketsServerPort = 1337;
   9:  
  10: var webSocketServer = require('websocket').server;
  11: var http = require('http');
  12:  
  13: //保存最近100条消息记录
  14: var history = [ ];
  15:  
  16: //当前连接的客户端
  17: var clients = [ ];
  18:  
  19: /**
  20:  * 对聊天内容进行字符转义
  21:  */
  22: function htmlEntities(str) {
  23:     return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  24: }
  25:  
  26:  
  27: var colors = [ 'red', 'green', 'blue', 'magenta', 'purple', 'plum', 'orange' ];
  28: colors.sort(function(a,b) { return Math.random() > 0.5; } );
  29:  
  30: /**
  31:  * HTTP server
  32:  */
  33: var server = http.createServer(function(request, response) {});
  34:  
  35: server.listen(webSocketsServerPort, function() {
  36:     console.log(getNow() + " WebSocket Server is listening on port:" + webSocketsServerPort);
  37: });
  38:  
  39: /**
  40:  * WebSocket server
  41:  * WebSocket server is tied to a HTTP server. To be honest I don't understand why.
  42:  */
  43: var wsServer = new webSocketServer({
  44:     httpServer: server
  45: });
  46:  
  47: //每一个客户端请求建立连接时,都将触发此方法
  48: wsServer.on('request', function(request) {
  49:  
  50:     console.log(getNow() + ' ' + request.origin + ' 请求连接.');
  51:  
  52:     // accept connection - you should check 'request.origin' to make sure that client is connecting from your website
  53:     // (http://en.wikipedia.org/wiki/Same_origin_policy)
  54:     var connection = request.accept(null, request.origin); 
  55:  
  56:     //保存当前请求连接客户端的索引,以方便在断开连接时,从连接池中移除该连接
  57:     var index = clients.push(connection) - 1;
  58:     var userName;
  59:     var userColor;
  60:  
  61:     console.log(getNow() + ' 已建立连接...');
  62:     
  63:     //推送历史聊天记录
  64:     if (history.length > 0) {
  65:         connection.sendUTF(JSON.stringify({type: 'history', data: history}));
  66:     }
  67:  
  68:     //某一客户端发送消息过来
  69:     connection.on('message', function(message) {
  70:         if (message.type === 'utf8') {
  71:             
  72:             //第一次请求用于保存用户信息
  73:             if (!userName) {
  74:                 userName = htmlEntities(message.utf8Data);
  75:                 
  76:                 userColor = colors.shift();
  77:                 connection.sendUTF(JSON.stringify({ type:'color', data: userColor }));
  78:                 console.log(getNow() + ' 用户已登录: ' + userName + ' -- ' + userColor);
  79:  
  80:             } else {
  81:                 //记录消息并广播
  82:                 console.log(getNow() + userName + '-说: ' + message.utf8Data);
  83:                 
  84:                 //传递给客户端的数据格式
  85:                 var obj = {
  86:                     time: (new Date()).getTime(),
  87:                     text: htmlEntities(message.utf8Data),
  88:                     author: userName,
  89:                     color: userColor
  90:                 };
  91:                 history.push(obj);
  92:  
  93:                 //取数组最后100条消息记录并保存
  94:                 history = history.slice(-100); 
  95:  
  96:                 //将消息广播给所有客户端
  97:                 var json = JSON.stringify({ type:'message', data: obj });
  98:                 for (var i=0; i < clients.length; i++) {
  99:                     clients[i].sendUTF(json);
 100:                 }
 101:                 
 102:                 console.log("总的客户端连接数:" + clients.length);
 103:             }
 104:         }
 105:     });
 106:  
 107:     //用户断开连接
 108:     connection.on('close', function(connection) {
 109:         if (!userName && !userColor) {
 110:             console.log(getNow() + " -- " + connection.remoteAddress + " 断开链接.");
 111:             
 112:             //从连接池中移除连接
 113:             clients.splice(index, 1);
 114:             
 115:             //回收访用户所使用的颜色
 116:             colors.push(userColor);
 117:         }
 118:     });
 119:  
 120: });
 121:  
 122: function getNow() {
 123:     return new Date().format('yyyy-MM-dd hh:mm:ss');
 124: }
 125:  
 126: Date.prototype.format = function (fmt) { //author: meizz   
 127:     var o = {
 128:         "M+": this.getMonth() + 1,
 129:         "d+": this.getDate(),   
 130:         "h+": this.getHours(),   
 131:         "m+": this.getMinutes(),  
 132:         "s+": this.getSeconds(),   
 133:         "q+": Math.floor((this.getMonth() + 3) / 3),   
 134:         "S": this.getMilliseconds()   
 135:     };
 136:     if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
 137:     for (var k in o)
 138:     if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
 139:     return fmt;
 140: }

运行supervisor chat-server.js或者node chat-server.js 就OK了~

 

使用Firefox测试一下:)

image

 

本文参考:

1、Node.js & WebSocket - Simple chat tutorial

2、WebSocket-Node

目录
相关文章
|
9天前
|
存储 JavaScript 前端开发
webSocket+Node+Js实现在线聊天(包含所有代码)
文章介绍了如何使用WebSocket、Node.js和JavaScript实现在线聊天功能,包括完整的前端和后端代码示例。
42 0
|
2月前
|
JavaScript 前端开发 网络协议
Vue.js 与 WebSocket 的惊世联姻!实时数据通信的震撼变革,你敢错过?
【8月更文挑战第30天】在现代Web开发中,实时数据通信至关重要。Vue.js作为流行前端框架,结合WebSocket技术,实现了高效实时的数据交互。本文简要介绍了WebSocket原理及其在Vue.js项目中的应用方法,包括建立连接、监听事件及数据处理等步骤,展示了如何利用二者结合轻松应对实时聊天、股票更新等多种场景,为开发者提供了实用指南。希望本文能帮助您更高效地实现Web应用的实时通信功能。
106 0
|
11天前
|
JavaScript 前端开发 开发工具
五子棋小游戏(JS+Node+Websocket)可分房间对战
本文介绍了通过JS、Node和WebSocket实现的五子棋游戏,支持多人在线对战和观战功能。
20 1
五子棋小游戏(JS+Node+Websocket)可分房间对战
|
4月前
|
JavaScript 网络协议 前端开发
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
387 0
|
5月前
|
监控 JavaScript API
局域网监控软件的实时通知系统:利用Node.js和WebSocket实现即时消息推送
本文介绍了如何使用Node.js和WebSocket构建局域网监控软件的实时通知系统。实时通知对于网络安全和家庭监控至关重要,能即时发送监控数据变化的通知,提高响应速度。通过Node.js创建WebSocket服务器,当数据变化时,监控软件发送消息至服务器,服务器随即推送给客户端。此外,还展示了如何利用Node.js编写API,自动将监控数据提交到网站,便于用户查看历史记录,从而提升监控体验。
157 3
|
2月前
|
JavaScript 前端开发 网络协议
抖音直播弹幕数据逆向:websocket和JS注入
抖音直播弹幕数据逆向:websocket和JS注入
202 1
|
4月前
vue.js+node.js+mysql在线聊天室源码
vue.js+node.js+mysql在线聊天室源码 技术栈:vue.js+Element UI+node.js+socket.io+mysql
159 3
|
8天前
|
JavaScript
NodeJs的安装
文章介绍了Node.js的安装步骤和如何创建第一个Node.js应用。包括从官网下载安装包、安装过程、验证安装是否成功,以及使用Node.js监听端口构建简单服务器的示例代码。
NodeJs的安装
|
7天前
|
存储 JavaScript 前端开发
Node 版本控制工具 NVM 的安装和使用(Windows)
本文介绍了NVM(Node Version Manager)的Windows版本——NVM for Windows的安装和使用方法,包括如何安装Node.js的特定版本、列出已安装版本、切换使用不同版本的Node.js,以及其他常用命令,以实现在Windows系统上对Node.js版本的便捷管理。
Node 版本控制工具 NVM 的安装和使用(Windows)
|
23天前
|
SQL JavaScript 数据库
sqlite在Windows环境下安装、使用、node.js连接
sqlite在Windows环境下安装、使用、node.js连接