简单介绍 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,原来这么简单的更多相关文章

  1. 我在阿里这仨月 前端开发流程 前端进阶的思考 延伸学习的方式很简单:google 一个关键词你能看到十几篇优秀的博文,再这些博文中寻找新的关键字,直到整个大知识点得到突破

    我在阿里这仨月 Alibaba 试用期是三个月,转眼三个月过去了,也到了转正述职的时间.回想这三个月做过的事情,很多很杂,但还是有重点. 本文谈一谈工作中遇到的各种场景,需要用到的一些前端知识,以及我 ...

  2. 如何学习 websocket ?

    如何学习 websocket ? 使用 HTML https://github.com/phoboslab/jsmpeg MPEG1 进行播放 https://w3c.github.io/media- ...

  3. phpunit测试学习 1:一点简单的扼要有用的东西的总结 一点入门认识

    16:45 2015/12/8phpunit测试学习 1:一点简单的扼要有用的东西的总结  一点入门认识 具体的入门安装和入门实践请参照文中的推荐博客或网上其他博客推荐博客,我感觉这几篇博客写得很不错 ...

  4. Quartz定时任务学习(一)简单任务

    学习quartz首先了解三个概念: 调度器:负责调度作业和触发器: 触发器:设置作业执行的时间.参数.条件等:(简单触发器和Cron触发器) 作业:定时任务内容,被执行的程序: 下载必要的jar包,直 ...

  5. WebSocket就是这么简单

    前言 今天在慕课网上看到了Java的新教程(Netty入门之WebSocket初体验):https://www.imooc.com/learn/941 WebSocket我是听得很多,没有真正使用过的 ...

  6. [转]ZooKeeper学习第一期---Zookeeper简单介绍

    ZooKeeper学习第一期---Zookeeper简单介绍 http://www.cnblogs.com/sunddenly/p/4033574.html 一.分布式协调技术 在给大家介绍ZooKe ...

  7. Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息

    </pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...

  8. Spring MVC 学习笔记9 —— 实现简单的用户管理(4)用户登录显示局部异常信息

    Spring MVC 学习笔记9 -- 实现简单的用户管理(4.2)用户登录--显示局部异常信息 第二部分:显示局部异常信息,而不是500错误页 1. 写一个方法,把UserException传进来. ...

  9. Spring MVC 学习笔记8 —— 实现简单的用户管理(4)用户登录

    Spring MVC 学习笔记8 -- 实现简单的用户管理(4)用户登录 增删改查,login 1. login.jsp,写在外面,及跟WEB-INF同一级目录,如:ls Webcontent; &g ...

  10. LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS

    LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163. ...

随机推荐

  1. Spring事务——传播性

    传播性 事务传播行为是为了解决业务层方法之间互相调用的事务问题,当一个事务方法被另一个事务方法调用时,事务该以何种状态存在?例如新方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运 ...

  2. python入门教程之八列表,字典,字符串,集合常用操作

    一列表常用方法 Python包含以下函数: 序号 函数 1 cmp(list1, list2)比较两个列表的元素 2 len(list)列表元素个数 3 max(list)返回列表元素最大值 4 mi ...

  3. MySQL笔记之一致性视图与MVCC实现

    一致性读视图是InnoDB在实现MVCC用到的虚拟结构,用于读提交(RC)和可重复度(RR)隔离级别的实现. 一致性视图没有物理结构,主要是在事务执行期间用来定义该事物可以看到什么数据. 一.Read ...

  4. 五月八号java基础知识点

    1.对于容器中元素进行访问时,经常需要按照某种次序对容器中的每个元素访问且仅访问 一次,这就是遍历,也称为迭代.2.遍历是指从容器中获得当前元素的后续元素.对元素的遍历有很多种:第一种就是foreac ...

  5. layUI之DataTable组件V1.0(父子表管理传值/数据表格与select&laydate结合等)

    layUI之DataTable数据表格组件V1.0 目录 layUI之DataTable数据表格组件V1.0 概述 一.下载与引用 二.组件功能介绍 三.父表格渲染 1. HTML中声明空table一 ...

  6. 苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

    开心一刻 2023年元旦,我妈又开始了对我的念叨 妈:你到底想多少岁结婚 我:60 妈:60,你想找个多大的 我:找个55的啊,她55我60,结婚都有退休金,不用上班不用生孩子,不用买车买房,成天就是 ...

  7. C# 监听窗口分辨率/DPI变更

    当程序运行,窗口已经加载后,如果修改屏幕分辨率,会影响窗口的正常显示. 举个案例: 悬浮窗口,显示在屏幕右下角.当分辨率.文本显示比例变更后,窗口位置可能会超出屏幕范围. 所以当屏幕变更时,我们需要知 ...

  8. 用Aspose-Java免费实现 PDF、Word、Excel、Word互相转换并将转换过得文件上传OSS,返回转换后的文件路径

    嘿嘿嘿.嘿嘿,俺又回来了! github代码地址 https://github.com/Tom-shushu/work-study 接口文档有道云 https://note.youdao.com/s/ ...

  9. AutoCAD二次开发系列教程01-如何在AutoCAD中输出Hello World

    目录 01项目环境准备 02代码示例 03输出示例 04总结 05源码地址 01项目环境准备 A.开发使用的软件:AutoCAD2016.VisualStudio2022 B.建立依赖的本地库(提前从 ...

  10. Java中数字相关的类有哪些?Nuber数字类和Math数学类详解

    前言 我们在解决实际问题时,会经常对数字.日期和系统设置进行处理,比如在我们的代码中,经常会遇到一些数字&数学问题.随机数问题.日期问题和系统设置问题等. 为了解决这些问题,Java给我们提供 ...