学习websocket,原来这么简单
简单介绍 websocket
WebSocket是一种在TCP连接上进行全双工通信的协议。
WebSocket通信协议于2011年被IETF定为标准。
然后WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,
允许服务端主动向客户端推送数据。
在WebSocket API中,浏览器和服务器只需要完成一次握手。
两者之间就直接可以创建持久性的连接,并进行双向数据传输。
我们为什么要使用 websocket
我们都知道 HTTP 协议有一个缺陷。
那就是通信只能由客户端发起。服务端没法主动发起。
有些场景我们需要让客户端实时知道消息。
虽然可以使用轮询来解决这个问题。
但是非常浪费资源,因为要不停连接,断开后又继续连接。
这个时候我们就需要使用 websocket
websocket 应用场景
1.弹幕媒体聊天 [客服推送]
2.协同编辑 [wps]
3.基于位置的应用 [外卖]
4.体育实况更新
5.股票帮金报价实时更新
websocket 和HTTP请求的不同点:
1.WebSocket是双向通信协议,HTTP是单向的
WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。而HTTP是单向的
2.连接方式不同
WebSocket是需要浏览器和服务器握手进行建立连接的。
http是浏览器发起向服务器的连接,服务器预先并不知道这个连接。
3.协议开头不同
websocket:websocket的协议是以 ws/wss 开头。
http 对应的是 http/https
4.连接长度不同
websocket是持久连接。http 是短连接。
简单实现一下 WebSocket
node创建WebSocket
我们需要先下载 npm install ws
ws是一个简单易用、快速且经过全面测试的WebSocket客户端和服务器实现。
我们就直接使用就好了
const express = require('express')
const app = express()
const port = 3000
// 托管静态资源-express.static()
app.use(express.static('public'))
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
// 引入 ws,并且解构使用我们需要的 WebSocketServer
const { WebSocketServer } = require('ws');
// 创建WebSocketServer的实例wss,并指定端口号
const wss = new WebSocketServer({ port: 8080 });
// 通过实例wss进行监听
wss.on('connection', function connection(ws) {
ws.on('error', console.error);
// 接收客户端发送过来的消息
ws.on('message', function message(data) {
console.log('客户端发送过来的消息', data);
});
ws.send('服务端发送的消息');
});
客户端 WebSocket 的创建
我们需要创建 WebSocket 的实例同时指定端口号。
然后通过 onopen onmessage onerror 来判断ws的状态事件
下面我们就来简单写一下
<body>
<h1>欢迎 学习WebSocket </h1>
</body>
<script>
// 创建 WebSocket并指定一个地址
let ws = new WebSocket('ws://localhost:8080')
// 是否链接成功
ws.onopen = (() => {
console.log("链接成功")
})
// 监听服务端发送过来的消息
ws.onmessage = ((messObj) => {
console.log('发送过来的消息', messObj)
})
// 连接失败
ws.onerror = (() => {
console.log('连接失败')
})
</script>
客户端发送消息给服务端
我们需要写一个简单的html界面,
获取到 文本域中的内容。
然后通过 ws.send(textareaValue) 给服务端发送消息。
服务端在
ws.on('message', function message(data) {
console.log(data)
})
这个方法中接收客户端的消息
data就是客户端发送过来的消息
如果是二进制数据,我们可以使用 data.toString()进行转换
<body>
<h1>欢迎 学习WebSocket </h1>
<textarea rows="10" cols="30" id="textarea" placeholder="请输入内容"></textarea>
<button onclick="sendHandler()">点击按钮</button>
</body>
// 创建 WebSocket并指定一个地址
let ws = new WebSocket('ws://localhost:8080')
let textarea=document.getElementById('textarea')
function sendHandler(){
const textareaValue = textarea.value;
// 通过ws.send给客户端发送消息
ws.send(textareaValue)
}
WebSocket 实现广播
我们要做一个广播。
就有点类似在QQ群中发送一条消息,
在这个群中的其他用户可以接收到这条消息。
WebSocket 连接成功后,wss.clients来获取当前服务端连接了多少个客户端。
wss.clients是一个Set类型的。我们通过 forEach 来进行遍历。
我们通过 client.readyState 的状态是否是 WebSocket.OPEN
然后调用 client.send(data, { binary:false })就数据发送出去
// 引入 ws,并且解构使用我们需要的 WebSocketServer
const { WebSocketServer, WebSocket } = require('ws');
// import { WebSocketServer } from 'ws';
// 创建WebSocketServer的实例wss,并指定端口号
const wss = new WebSocketServer({ port: 8080 });
// 通过实例wss进行监听
wss.on('connection', function connection(ws) {
ws.on('error', console.error);
// 客户端
ws.on('message', function message(data) {
console.log('received: %s', data);
// 服务器广播
// 广播到所有连接的WebSocket客户端,包括其自身。
console.log('连接了多少个',wss.clients.size)
wss.clients.forEach(function each(client) {
// 判断当前连接服务端的所有客户端的ws。
if (client.readyState === WebSocket.OPEN) {
// binary表示数据是否是二进制。binary:false表示不是二进制
client.send(data, { binary:false });
}
});
});
ws.send('服务端发送的消息');
});
发现自己也被广播了
假设不同的浏览器代码一个用户。
通过上面的图片,我们发现谷歌浏览器发送一条消息。
虽然火狐浏览器接收到了。但是谷歌发送的消息自己也接收到了。
这样明显是不正确的。因此。我们处理一下。
自己发送的消息不需要广播自己的。
我们使用 client!==ws 来进行判断
// 引入 ws,并且解构使用我们需要的 WebSocketServer
const { WebSocketServer, WebSocket } = require('ws');
// import { WebSocketServer } from 'ws';
// 创建WebSocketServer的实例wss,并指定端口号
const wss = new WebSocketServer({ port: 8080 });
// 通过实例wss进行监听
wss.on('connection', function connection(ws) {
ws.on('error', console.error);
// 客户端
ws.on('message', function message(data) {
console.log('received: %s', data);
// 服务器广播
// 广播到所有连接的WebSocket客户端,包括其自身。
console.log('连接了多少个',wss.clients.size)
wss.clients.forEach(function each(client) {
// 判断当前连接服务端的所有客户端的ws用户。
// client!==ws 表示不是当前发送的用户[不要自己广播自己]
if (client!==ws && client.readyState === WebSocket.OPEN) {
// binary表示数据是否是二进制。binary:false表示不是二进制
client.send(data, { binary:false });
}
});
});
// 第一次连接成功后发送的消息。
ws.send('');
});
实现关闭页面关闭 WebSocket
当我们离开连接 WebSocket的页面离开后,
我们应该关闭当前连接。
可是现在我们点击去user页面的时候,并没有关闭连接。
这显然是不太好的。所以我们需要优化一下。
当用户离开,我们需要关闭连接
// 关闭当前窗口,按下 F5 或点击以下链接触发 onbeforeunload 事件
document.body.onbeforeunload = function () {
ws.close()
return 'close'
}
//离开当前页面会触发
window.onunload = function (e) {
var e = window.event || e;
console.log('===>',e)
// 离开页面,关闭WebSocket
ws.close()
}
携带token
我们在连接 WebSocket 的时候,
没有鉴权,也就是说无法判断当前这个用户的信息。
这样是不安全的。
因此我们在连接 WebSocket 需要携带token.
通过这样的形式携带 ws://localhost:8080?token=' + 'tokne_zahngsan'
// 创建 WebSocket并指定一个地址,并且携带一个token
let ws = new WebSocket('ws://localhost:8080?token=' + 'tokne_zahngsan')
//省略其他代码
wss.on('connection', function connection(ws,req) {
// 获取前端携带的token
console.log('req', req.url.slice(8))
})
学习websocket,原来这么简单的更多相关文章
- 我在阿里这仨月 前端开发流程 前端进阶的思考 延伸学习的方式很简单:google 一个关键词你能看到十几篇优秀的博文,再这些博文中寻找新的关键字,直到整个大知识点得到突破
我在阿里这仨月 Alibaba 试用期是三个月,转眼三个月过去了,也到了转正述职的时间.回想这三个月做过的事情,很多很杂,但还是有重点. 本文谈一谈工作中遇到的各种场景,需要用到的一些前端知识,以及我 ...
- 如何学习 websocket ?
如何学习 websocket ? 使用 HTML https://github.com/phoboslab/jsmpeg MPEG1 进行播放 https://w3c.github.io/media- ...
- phpunit测试学习 1:一点简单的扼要有用的东西的总结 一点入门认识
16:45 2015/12/8phpunit测试学习 1:一点简单的扼要有用的东西的总结 一点入门认识 具体的入门安装和入门实践请参照文中的推荐博客或网上其他博客推荐博客,我感觉这几篇博客写得很不错 ...
- Quartz定时任务学习(一)简单任务
学习quartz首先了解三个概念: 调度器:负责调度作业和触发器: 触发器:设置作业执行的时间.参数.条件等:(简单触发器和Cron触发器) 作业:定时任务内容,被执行的程序: 下载必要的jar包,直 ...
- WebSocket就是这么简单
前言 今天在慕课网上看到了Java的新教程(Netty入门之WebSocket初体验):https://www.imooc.com/learn/941 WebSocket我是听得很多,没有真正使用过的 ...
- [转]ZooKeeper学习第一期---Zookeeper简单介绍
ZooKeeper学习第一期---Zookeeper简单介绍 http://www.cnblogs.com/sunddenly/p/4033574.html 一.分布式协调技术 在给大家介绍ZooKe ...
- Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息
</pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...
- Spring MVC 学习笔记9 —— 实现简单的用户管理(4)用户登录显示局部异常信息
Spring MVC 学习笔记9 -- 实现简单的用户管理(4.2)用户登录--显示局部异常信息 第二部分:显示局部异常信息,而不是500错误页 1. 写一个方法,把UserException传进来. ...
- Spring MVC 学习笔记8 —— 实现简单的用户管理(4)用户登录
Spring MVC 学习笔记8 -- 实现简单的用户管理(4)用户登录 增删改查,login 1. login.jsp,写在外面,及跟WEB-INF同一级目录,如:ls Webcontent; &g ...
- LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS
LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163. ...
随机推荐
- [软件测试]Web接口的性能测试
1 接口响应性能影响因素分析 影响Web接口查询响应性能的重要因素: 1.网络/带宽.服务器硬件资源(CPU.内存.磁盘) 2.用户并发数 3.查询的基础数据集的量级.百万级?亿级?百亿级? 4.查询 ...
- [Java EE]解决浏览器跨域问题
1 解决浏览器跨域问题的方案 方式1: 浏览器(chrome)中取消跨域限制 step1 浏览器 chrome://flags step2 搜索:same step3 将搜索结果中的3个插件[Same ...
- 【SpringBoot2】 SpringBoot2核心技术 基础
写在前面 1 SpringBoot2核心技术 基础 1.1 Spring与SpringBoot SpringBoot是一个高层框架 1.2 项目创建 1.2.1 创建POM ①导入spring-boo ...
- 记一次 .NET某医疗器械清洗系统 卡死分析
一:背景 1. 讲故事 前段时间协助训练营里的一位朋友分析了一个程序卡死的问题,回过头来看这个案例比较经典,这篇稍微整理一下供后来者少踩坑吧. 二:WinDbg 分析 1. 为什么会卡死 因为是窗体程 ...
- 【FAQ】关于华为推送服务因营销消息频次管控导致服务通讯类消息下发失败的解决方案
一. 问题描述 使用华为推送服务下发IM消息时,下发消息请求成功且code码为80000000,但是手机总是收不到消息: 在华为推送自助分析(Beta)平台查看发现,消息发送触发了频控. 二. 问题原 ...
- Android JAVA连接MQTT,以及常见问题
本文介绍如何使用Android(JAVA)客户机连接MQTT服务器 第一步先引入MQTT 在 build.gradle 添加以下: dependencies { implementation 'org ...
- JUC中常见的集合
Map: HashMap ===> ConcurrentHashMap List: ArrayList ===> CopyOnWriteArrayList Set: HashSet === ...
- vue中使用西瓜视频api
https://v2.h5player.bytedance.com/en/api/ 1 npm install xgplayer 1 <div id="mse">< ...
- 使用 Sa-Token 完成踢人下线功能
一.需求 在企业级项目中,踢人下线是一个很常见的需求,如果要设计比较完善的话,至少需要以下功能点: 可以根据用户 userId 踢出指定会话,对方再次访问系统会被提示:您已被踢下线,请重新登录. 可以 ...
- 2021-05-24:盛最多水的容器。给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai)
2021-05-24:盛最多水的容器.给你 n 个非负整数 a1,a2,-,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 ...