博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【转载】Node.js + WebSocket 实现的简易聊天室
阅读量:6983 次
发布时间:2019-06-27

本文共 8081 字,大约阅读时间需要 26 分钟。

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

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, '&').replace(//g, '>').replace(/"/g, '"');
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、

2、

分类: 

转载于:https://www.cnblogs.com/fx2008/archive/2012/11/01/2750106.html

你可能感兴趣的文章
C++复习考点
查看>>
一道事件环面试题引发的思考
查看>>
url的校验
查看>>
Flex容器
查看>>
mysql Can't connect to MySQL server on '' (61)错误记录
查看>>
JVM垃圾回收机制
查看>>
深入剖析Vue源码 - 组件进阶
查看>>
记一次dll构建时机优化
查看>>
【译】Redis Hyperloglog 的转换
查看>>
mysql修改密码
查看>>
《以太坊白皮书》笔记(1)—— 比特币介绍
查看>>
babel es6 to es5
查看>>
【软件开发底层知识修炼】二 深入浅出处理器之二 中断的概念与意义
查看>>
electron打包更新与集成sqlite小总结
查看>>
CentOS 安装 pip
查看>>
React性能优化之代码分割
查看>>
Springmvc+mybatis+shiro+ZooKeeper+Redis+KafKa
查看>>
vue电商项目商品详情放大镜插件
查看>>
深入解析JSON与XML优缺点对比
查看>>
Java行为参数化(二)-Lambda表达式
查看>>