首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >带你揭开WebSocket的神秘面纱!

带你揭开WebSocket的神秘面纱!

作者头像
用户7413032
发布2020-06-11 16:18:19
9520
发布2020-06-11 16:18:19
举报
文章被收录于专栏:佛曰不可说丶佛曰不可说丶

写在前面

在揭开webSocket的神秘面纱之前,有言在先,我在写文章之前对webSocket一无所知,由于公司业务用到,故此研究记录一下,班门弄斧之处,请大佬批评指正!

废话少说,老规矩,从前世今生讲起

什么是webSocket

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议 。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输。

听了官方的解释,你是不是又像在读文言文,下面我们给他赋予一种通俗的解释

WebSocket 是一种网络通信协议,他可以让服务器将数据主动推送给客户端

说白了,他就是能给数据主动推送给客户端,接下来我们又有疑问了,为啥我们需要他呢?

为什么需要webSocket

我们不是有了http这种万能协议,为啥还需要这玩意嘞!因为http不能完成服务端推送啊,有人又要问了,新出来的HTTP/2不是可以吗?HTTP/2 只能推送静态资源,无法推送即使的信息。啥意思呢? 经过多方探寻发现HTTP/2 所谓的server push其实是当服务器接收一个请求时,可以响应多个资源。

举个例子:当我想要去请求服务器中的a.html,服务器不仅把a.html给我们,还可以把js、css等文件也一并扔给我们。最直观的好处就是,浏览器不用解析页面再发起请求来获取数据,节约了页面加载时间。 所以HTTP/2并不是webSocket的替代方案,如果我们要实现即时通讯,那么webSocket当然不可代替

怎么用webSocket

在知道怎么用webSocket之前我们现来研究一下他的原理

原理

如果上图所示: http和webSocket其实是个交集,他们的使用都是建立在tcp链接之上。

要想使用webSocket与server建立链接,首先需要去建立一个tcp链接,然后握手阶段采用的是 HTTP/1.1 协议,实际上我认为他就是借用一部分http协议的东西来达到他的能力

下面我们看来看看他是怎么搞的呢?

如上图所示,我们在ws中就能看到这个持久的webSocket

点开一看,是个这玩意,下面我们来喜喜探究一下

//请求消息
GET wss://webchat-bj-test5.clink.cn&province= HTTP/1.1 //请求地址
Host: webchat-bj-test5.clink.cn  //域名
Connection: Upgrade
Pragma: no-cache  
Cache-Control: no-cache  //缓存相关
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.9 Safari/537.36 //ua
Upgrade: websocket  //下面这些就是websocket这些东西了
Origin: http://clink2.clink.cn:5050
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Sec-WebSocket-Key: O5GLCYKZVQi2jTLENobvtg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
//响应消息
HTTP/1.1 101 // 响应行,告诉你版本相关
Server: nginx/1.13.9  //服务器用的啥
Date: Mon, 30 Mar 2020 09:21:00 GMT   
Connection: upgrade
Vary: Origin
Vary: Access-Control-Request-Method  //跨域相关
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Upgrade: websocket    //下面这些就是websocket的东西了
Sec-WebSocket-Accept: uZpmP+PDDvSeKsEg9vkAsWcqPzE=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15

上面两段代码你就会发现,他是在http的基础上加了点东西,告诉服务器,我是个websocket请求 服务器做了解析和处理以后就能结结实实的通信了!

接下来介绍请求和相应消息的知识点了

  • 1、协议标识符是ws(如果加密,则为wss),服务器网址就是 URL
  • 2、Sec-WebSocket-Key 是一个Base64 encode的值,这个是浏览器随机生成的,用于验证跟服务器是不是能对眼
  • 3、Sec—WebSocket-Protocol 是一个列出的客户端请求的子协议,服务端应按照优先顺序排列
  • 4、Sec-WebSocket-Version 是告诉服务器所使用的Websocket Draft(协议版本)
  • 5、Upgrade 是告诉客户端我们成功切换成websocket协议了
  • 6、Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key(我觉得底层用的是非对称加密)

如此之后算是建立了一个websocket链接

如何使用

用法方面相当简单,我们照着mdn一顿操作即可

//首先new一个websocket对象,
var ws = new WebSocket("wss://webchat-bj-test5.clink.cn");
//实例对象的onopen属性,用于指定连接成功后的回调函数。
ws.onopen = function(evt) { 
  console.log("Connection open ..."); 
  //实例对象的send()方法用于向服务器发送数据。
  ws.send("Hello WebSockets!");
};
//实例对象的onmessage属性,用于指定收到服务器数据后的回调函数。
ws.onmessage = function(evt) {
  console.log( "Received Message: " + evt.data);
  ws.close();
};
//实例对象的onclose属性,用于指定连接关闭后的回调函数。
ws.onclose = function(evt) {
  console.log("Connection closed.");
};     

以上阮一峰大佬的例子,基本涵盖了常用的使用场景,如果好奇,请mdn找寻答案

当然,原生的东西是相当不好用的,因为你虽然建立了链接,后端处理器起来却不是那么得心应手,所以在这个时候牛逼的库又诞生了,再次我隆重推荐 socketIO

SocketIO

SocketIO将WebSocket、AJAX和其它的通信方式全部封装成了统一的通信接口,也就是说,我们在使用SocketIO时,不用担心兼容问题,底层会自动选用最佳的通信方式。因此说,WebSocket是SocketIO的一个子集。

废话少说上代码

node端
//引入koa
var app = require('koa')();
//创建http服务
var server = require('http').createServer(app.callback());
//给http封装成io对象
var io = require('socket.io')(server);
// 建立链接
io.on('connection', function(socket){
// io.emit代表广播,socket.emit代表私发
socket.on('eventB', function(socket){ /* */ });

socket.emit('eventA', /* */);
});
server.listen(3000);
//前端
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
<script>
    //创建个服务
    var socket = new io()
        用on监听
        socket.on('eventA', function (res) {
        console.log('⽤户1接收到信息了了')
    })
    socket.emit('eventB', data)
</script>

到此就算用框架实现了完整的即使消息

兼容问题

在2020年的今天这个兼容已经相当乐观了,请放心使用!

websocket的特点(重点:面试要考)

  • 1、建立在 TCP 协议之上,服务器端的实现比较容易。
  • 2、与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  • 3、数据格式比较轻量,性能开销小,通信高效。
  • 4、可以发送文本,也可以发送二进制数据。
  • 5、没有同源限制,客户端可以与任意服务器通信。

目前web即时通讯的方案

1、ajax轮询

ajax轮询 的原理非常简单,让浏览器隔个几秒就发送一次请求,问问服务器有没有新消息。这个访问,对后端非常友好,无限调用接口即可,但是有个非常致命的缺点,浪费带宽和服务器资源。小型应用还扛得住,但是万一又成千上万的人想要即时消息呢?这就不能满足了

2、long poll(长轮询)

其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。这样做是解决了无限调用接口的弊端,但是却一直维护了一个长链接,会让一个http请求一直处在pedding状态!服务器压力也是相当大,所以,还是不可取

3、websocket

这就是我们今天的主角了,难道他就没缺点吗?

当然有了,由于传输数据需要进行二次解析,增加开发成本及难度,所以公司得多花钱了

SSE

评论中有同学说到了sse,下面我们来探索一下

所谓SSE(Sever-Sent Event),就是浏览器向服务器发送一个HTTP请求,保持长连接,服务器不断单向地向浏览器推送“信息”(message),这么做是为了节约网络资源,不用一直发请求,建立新连接。

看了概念你就会发现,他其实就是类似长轮询,他有一个浏览器内置EventSource对象来操作

//进建立链接
var source = new EventSource();
//关闭链接
source.close();

优缺点

优点就是当然是他是一个http的请求啊,由于被浏览器封装了,所以使用简单,节约开发成本

缺点也相当明显,无法实现双向消息

后记

首先先感谢各位大佬的文章

WebSocket 教程 聊一聊Web端的即时通讯

由于工作需要,学习了websocket,并整理再次,帮助大家一篇文章全搞定,不用谢我,请叫我雷锋!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020年03月31日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 什么是webSocket
  • 为什么需要webSocket
  • 怎么用webSocket
    • 原理
      • 如何使用
        • SocketIO
      • 兼容问题
        • websocket的特点(重点:面试要考)
        • 目前web即时通讯的方案
          • 1、ajax轮询
            • 2、long poll(长轮询)
              • 3、websocket
              • SSE
                • 优缺点
                • 后记
                相关产品与服务
                即时通信 IM
                即时通信 IM(Instant Messaging)基于腾讯二十余年的 IM 技术积累,支持Android、iOS、Mac、Windows、Web、H5、小程序平台且跨终端互通,低代码 UI 组件助您30分钟集成单聊、群聊、关系链、消息漫游、群组管理、资料管理、直播弹幕和内容审核等能力。适用于直播互动、电商带货、客服咨询、社交沟通、在线课程、企业办公、互动游戏、医疗健康等场景。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档