深入剖析WebSocket的原理

本文来自:https://zhuanlan.zhihu.com/p/32845970,觉得不错,现在收藏分享给大家。
参考链接:https://blog.csdn.net/weixin_41486034/article/details/106240240

深入剖析WebSocket的原理

前言

针对以上您提起的WebSocket的相关话题,给您做一下系统的梳理,WebSocket是和http类似的可以实现全双工可持久连接通信的应用层协议,以下深入剖析一下WebSocket的原理。

什么是WebSocket

首先,我们需要弄明白,WebSocket本质上一种计算机网络应用层的协议,用来弥补http协议在持久通信能力上的不足。

我们知道http协议本身是无状态协议,每一个新的http请求,只能通过客户端主动发起,通过 建立连接–>传输数据–>断开连接 的方式来传输数据,传送完连接就断开了,也就是这次http请求已经完全结束了(虽然http1.1增加了keep-alive请求头可以通过一条通道请求多次,但本质上还是一样的)。

并且服务器是不能主动给客户端发送数据的(因为之前的请求得到响应后连接就断开了,之后服务器根本不知道谁请求过),客户端也不会知道之前请求的任何信息。
在这里插入图片描述
在这里插入图片描述
所以说,http协议本身是没有持久通信能力的,但是我们在实际的应用中,是很需要这种能力的,所以WebSocket协议由此而生,于2011年被IETF定为标准RFC6455,并被RFC7936所补充规范。

并且在HTML5标准中增加了有关WebSocket协议的相关api,所以只要实现了HTML5标准的客户端,就可以与支持WebSocket协议的服务器进行全双工的持久通信了。
在这里插入图片描述
ps:这里的持久通信能力指的是协议本身的能力,我们当然可以通过编程的方式实现这种功能,比如轮询的方式,但谁不喜欢原生就支持呢?

ps2:计算机网络里还有socket关键字,这里的socket指的是运输层协议的某一端,泛指某个应用程序。

ps3: unix编程里还有一个socket接口,这里的译名是套接字,泛指应用层协议的端口号。

WebSocket协议的原理

与http协议一样,WebSocket协议也需要通过已建立的TCP连接来传输数据。具体实现上是通过http协议建立通道,然后在此基础上用真正的WebSocket协议进行通信,所以WebSocket协议和http协议是有一定的交叉关系的。
在这里插入图片描述
下面是WebSocket协议请求头:
在这里插入图片描述
其中请求头中重要的字段:

Connection:Upgrade

Upgrade:websocket

Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits

Sec-WebSocket-Key:mg8LvEqrB2vLpyCNnCJV3Q==

Sec-WebSocket-Version:13
  1. Connection和Upgrade字段告诉服务器,客户端发起的是WebSocket协议请求

  2. Sec-WebSocket-Extensions表示客户端想要表达的协议级的扩展

  3. Sec-WebSocket-Key是一个Base64编码值,由浏览器随机生成

  4. Sec-WebSocket-Version表明客户端所使用的协议版本

而得到的响应头中重要的字段:

Connection:Upgrade

Upgrade:websocket

Sec-WebSocket-Accept:AYtwtwampsFjE0lu3kFQrmOCzLQ=
  1. Connection和Upgrade字段与请求头中的作用相同

  2. Sec-WebSocket-Accept表明服务器接受了客户端的请求

Status Code:101 Switching Protocols

并且http请求完成后响应的状态码为101,表示切换了协议,说明WebSocket协议通过http协议来建立运输层的TCP连接,之后便与http协议无关了。

WebSocket协议具体内容请参考:https://github.com/zhangkaitao/websocket-protocol

WebSocket协议的优缺点

优点:

· WebSocket协议一旦建议后,互相沟通所消耗的请求头是很小的

· 服务器可以向客户端推送消息了

缺点:

· 少部分浏览器不支持,浏览器支持的程度与方式有区别

WebSocket协议的应用场景

· 即时聊天通信

· 多玩家游戏

· 在线协同编辑/编辑

· 实时数据流的拉取与推送

· 体育/游戏实况

· 实时地图位置

NodeJS的简单实现

服务端

// 安装ws模块// npm install ws// 新建index.js文件// -----
// 导入ws模块const WebSocket = require('ws')
// 新建一个WebSocketServerconst wss = new WebSocket.Server({ port: 3000 })
// 服务器监听连接事件
wss.on('connection', ws => {

// 服务器监听消息事件 
 ws.on('message', msg => {
console.log('服务器收到:', msg)
 })

// 服务器向客户端发送消息
 ws.send('这是服务器发送的信息')
})

客户端

<!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>Document</title></head><body><script>
// 这是浏览器原生支持的WebSocket API,在支持HTML5标准的浏览器上可以直接使用
var ws = new WebSocket('ws://localhost:3000')

// 当连接成功后就可以发送消息了
 ws.onopen = function() {
console.log('连接已建立')
   ws.send('这是客户端发出的信息')
 }
// 收到消息后做对应的处理
 ws.onmessage = function(e) {
console.log(e.data)
 }</script></body></html>

运行结果

服务器端
在这里插入图片描述
浏览器端

在这里插入图片描述希望能帮到大家。排版不易,请多多点赞和关注。谢谢!

猜你喜欢

转载自blog.csdn.net/weixin_41486034/article/details/106547476