websocket学习和群聊实现
websocket
协议可以实现前后端全双工通信,从而取代浪费资源的长轮询。在此协议的基础上,可以实现前后端数据、多端数据,真正的实时响应。在学习websocket
的过程中,实现了一个简化版群聊,过程和代码详细记录在这篇文章中。
本篇文章来自,引用、转载请指明出处。
查看更多知识,或者技术交流:请访问
1 概述
1.1 websocket 是什么?
- 建立在 tcp 协议之上的网络通信协议
- 全双工通信协议
- 没有同源限制
- 可以发送文本、二进制数据等
1.2 为什么需要 websocket?
了解计算机网络协议的人,应该都知道:http 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。
这种通信模型有一个弊端:http 协议无法实现服务器主动向客户端发起消息。
因此,如果在客户端想实时监听服务器变化,必须使用 ajax 来进行轮询,效率低,浪费资源。
而 websocket 就可以使得前后端进行全双工通信(两方都可以向对方进行数据推送),是真正的平等对话。
2 websocket 客户端
支持html5
的浏览器支持 websocket 协议:
var ws = new websocket(url); // 创建一个websocket对象
2.1 websocket 属性
属性 | 描述 |
---|---|
ws.readystate | 只读属性 readystate 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。 |
ws.bufferedamount | 只读属性 bufferedamount 已被 send() 放入正在队列中等待传输,但是还没有发出的 utf-8 文本字节数。 |
2.2 websocket 方法
属性 | 描述 |
---|---|
ws.send() | 数据发送 |
ws.close() | 关闭连接 |
2.3 websocket 事件
属性 | 描述 |
---|---|
open | 连接建立触发 |
message | 通信时触发 |
error | 出错触发 |
close | 关闭连接触发 |
2.4 代码实现
假设我们在本地8080
端口打开了websocket服务,那么,下面代码可以在浏览器中实现和这个服务的通信:
<body> <script> var ws = new websocket("ws://localhost:8080/"); // 建立连接触发 ws.onopen = function () { ws.send("open ws"); console.log("open ws"); }; // 接收服务端数据触发 ws.onmessage = function (evt) { var data = evt.data; console.log("data is ", data); }; // 断开连接触发 ws.onclose = function () { console.log("close ws"); }; </script> </body>
3 websocket 服务端
关于服务端实现,根据技术选型不同,可以选用不同的库和包。我这里使用的是
node
的ws
库来websocket服务端。
在提到的socket.io
库,在浏览器端的写法不兼容原生api,准确来说,它们自己实现了一套websocket。所以,使用的时候前后端都应该引用第三方库。这样就造成了代码迁移性,严重下降。
综上所述,ws
库有以下优点:
- 兼容性好,兼容浏览器原生api
- 长期维护,效果稳定
- 使用方便(往下看就知道了)
4 实现群聊
4.1 群聊 服务端实现
首先,在命令行中,安装ws
库: npm install ws --save
现在,利用ws
来实现一个监听8080
端口的websocket服务器,讲解都在代码注释里,一目了然:
const port = 8080; // 监听端口 const websocket = require("ws"); // 引入 ws 库 const wss = new websocket.server({ port: port }); // 声明wss对象 /** * 向除了本身之外所有客户端发送消息,实现群聊功能 * @param {*} data 要发送的数据 * @param {*} ws 客户端连接对象 */ wss.broadcasttoelse = function broadcast(data, ws) { wss.clients.foreach(function each(client) { if (client !== ws && client.readystate === websocket.open) { client.send(data); } }); }; /* 客户端接入,触发 connection */ wss.on("connection", function connection(ws, req) { let ip = req.connection.remoteaddress; // 通过req对象可以获得客户端信息,比如:ip,headers等 /* 客户端发送消息,触发 message */ ws.on("message", function incoming(message) { ws.send(message); // 向客户端发送消息 wss.broadcasttoelse(message, ws); // 向 其他的 客户端发送消息,实现群聊效果 }); });
4.2 群聊 客户端实现
为了方便编写,这里引入了jquery
和bootstrap
这两个库,只需要关注js代码即可。
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>群聊</title> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/jquery/3.3.0/jquery.min.js"></script> </head> <body> <div class="container"> <textarea class="form-control" rows="30" disabled="disabled" id="show-area"></textarea> <input type="text" class="form-control" placeholder="请输入聊天内容" id="chat-input"> <button type="button" class="btn btn-info" id="send-btn">发送</button> </div> <script> var username = parseint(math.random() * 1000, 10) // 随机用户名, 以标识身份 var sendbtn = $("#send-btn"), // 发送信息按钮 chatinput = $("#chat-input"), // 聊天信息输入框 showarea = $("#show-area") // 聊天信息展示框 var ws = new websocket("ws://localhost:8080/") // 初始化websocket对象 sendbtn.on("click", function () { var content = chatinput.val() if (content.length === 0) { return alert("请不要输入空白内容") } content = "at " + (new date()).tostring() + "\n" + "来自用户" + username + "\n" + content // 拼接用户信息、时间信息和消息 ws.send(content) // 发送消息 chatinput.val("") // 清空输入框 }) ws.onopen = function () { console.log("conncet open") } ws.onmessage = function (evt) { var data = evt.data showarea.val(showarea.val() + data + "\n\n") // 刷新聊天信息展示框:显示群聊信息 } ws.onclose = function () { console.log("connect close") } </script> </body> </html>
4.3 群聊 效果展示
首先启动我们的服务端代码:node server.js
。其中,server.js
是放置服务端代码的文件。
然后,我们打开2次编写的html
代码,这相当于,打开2个客户端。来检测群聊功能。
5. 相关资料
- 概念解释:
- http://www.ruanyifeng.com/blog/2017/05/websocket.html
- https://www.cnblogs.com/jingmoxukong/p/7755643.html
-
ws
文档:https://www.npmjs.com/package/ws
本篇文章来自,引用、转载请指明出处。
查看更多知识,或者技术交流:请访问
推荐阅读
-
PHP用swoole+websocket和redis实现web一对一聊天
-
Python实现同时兼容老版和新版Socket协议的一个简单WebSocket服务器
-
CURL的学习和应用(附多线程实现)
-
canvas学习和滤镜实现代码
-
canvas学习和滤镜实现
-
spring boot websocket stomp 实现广播通信和一对一通信聊天
-
使用WebSocket实现即时通讯(一个群聊的聊天室)
-
微服务学习笔记(2)——使用Consul 实现 MagicOnion(GRpc) 服务注册和发现
-
基于asp.net + easyui框架,一步步学习easyui-datagrid——实现分页和搜索(二)
-
从零开始学习Node.js系列教程之基于connect和express框架的多页面实现数学运算示例