iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >WebSocket中通信过程的示例分析
  • 500
分享到

WebSocket中通信过程的示例分析

2024-04-02 19:04:59 500人浏览 安东尼
摘要

小编给大家分享一下websocket中通信过程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!什么是 WebSocket

小编给大家分享一下websocket中通信过程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

什么是 WebSocket ?

WEBSocket 是一种标准协议,用于在客户端和服务端之间进行双向数据传输。但它跟 Http 没什么关系,它是基于 tcp 的一种独立实现。

以前客户端想知道服务端的处理进度,要不停地使用 ajax 进行轮询,让浏览器隔个几秒就向服务器发一次请求,这对服务器压力较大。另外一种轮询就是采用 long poll 的方式,这就跟打电话差不多,没收到消息就一直不挂电话,也就是说,客户端发起连接后,如果没消息,就一直不返回 Response 给客户端,连接阶段一直是阻塞的。

而 WebSocket 解决了 HTTP 的这几个难题。当服务器完成协议升级后( HTTP -> WebSocket ),服务端可以主动推送信息给客户端,解决了轮询造成的同步延迟问题。由于 WebSocket 只需要一次 HTTP 握手,服务端就能一直与客户端保持通信,直到关闭连接,这样就解决了服务器需要反复解析 HTTP 协议,减少了资源的开销。

WebSocket中通信过程的示例分析

随着新标准的推进,WebSocket 已经比较成熟了,并且各个主流浏览器对 WebSocket 的支持情况比较好(不兼容低版本 IE,IE 10 以下),有空可以看看。

WebSocket中通信过程的示例分析

使用 WebSocket 的时候,前端使用是比较规范的,js 支持 ws 协议,感觉类似于一个轻度封装的 Socket 协议,只是以前需要自己维护 Socket 的连接,现在能够以比较标准的方法来进行。

WebSocket中通信过程的示例分析

下面我们就结合上图具体来聊一下 WebSocket 的通信过程。

建立连接

客户端请求报文 Header

客户端请求报文:

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13

与传统 HTTP 报文不同的地方:

Upgrade: websocket
Connection: Upgrade

这两行表示发起的是 WebSocket 协议。

Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13

Sec-WebSocket-Key 是由浏览器随机生成的,提供基本的防护,防止恶意或者无意的连接。

Sec-WebSocket-Version 表示 WebSocket 的版本,最初 WebSocket 协议太多,不同厂商都有自己的协议版本,不过现在已经定下来了。如果服务端不支持该版本,需要返回一个 Sec-WebSocket-Versionheader,里面包含服务端支持的版本号。

创建 WebSocket 对象:

var ws = new websocket("ws://127.0.0.1:8001");

ws 表示使用 WebSocket 协议,后面接地址及端口

完整的客户端代码:

<script type="text/javascript">
 var ws;
 var box = document.getElementById('box');

 function startWS() {
 ws = new WebSocket('ws://127.0.0.1:8001');
 ws.onopen = function (msg) {
 console.log('WebSocket opened!');
 };
 ws.onmessage = function (message) {
 console.log('receive message: ' + message.data);
 box.insertAdjacenthtml('beforeend', '<p>' + message.data + '</p>');
 };
 ws.onerror = function (error) {
 console.log('Error: ' + error.name + error.number);
 };
 ws.onclose = function () {
 console.log('WebSocket closed!');
 };
 }

 function sendMessage() {
 console.log('Sending a message...');
 var text = document.getElementById('text');
 ws.send(text.value);
 }

 window.onbeforeunload = function () {
 ws.onclose = function () {}; // 首先关闭 WebSocket
 ws.close()
 };
</script>

服务端响应报文 Header

首先我们来看看服务端的响应报文:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

我们一行行来解释

  • 首先,101 状态码表示服务器已经理解了客户端的请求,并将通过 Upgrade 消息头通知客户端采用不同的协议来完成这个请求;

  • 然后,Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key;

  • 最后,Sec-WebSocket-Protocol 则是表示最终使用的协议。

Sec-WebSocket-Accept 的计算方法:

  • 将 Sec-WebSocket-Key 跟 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 拼接;

  • 通过 SHA1 计算出摘要,并转成 base64 字符串

注意:Sec-WebSocket-Key/Sec-WebSocket-Accept 的换算,只能带来基本的保障,但连接是否安全、数据是否安全、客户端 / 服务端是否合法的 ws 客户端、ws 服务端,其实并没有实际性的保证。

创建主线程,用于实现接受 WebSocket 建立请求:

def create_socket():
 # 启动 Socket 并监听连接
 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 try:
 sock.bind(('127.0.0.1', 8001))

 # 操作系统会在服务器 Socket 被关闭或服务器进程终止后马上释放该服务器的端口,否则操作系统会保留几分钟该端口。
 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 sock.listen(5)
 except Exception as e:
 logging.error(e)
 return
 else:
 logging.info('Server running...')

 # 等待访问
 while True:
 conn, addr = sock.accept() # 此时会进入 waiting 状态

 data = str(conn.recv(1024))
 logging.debug(data)

 header_dict = {}
 header, _ = data.split(r'\r\n\r\n', 1)
 for line in header.split(r'\r\n')[1:]:
 key, val = line.split(': ', 1)
 header_dict[key] = val

 if 'Sec-WebSocket-Key' not in header_dict:
 logging.error('This socket is not websocket, client close.')
 conn.close()
 return

 magic_key = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
 sec_key = header_dict['Sec-WebSocket-Key'] + magic_key
 key = base64.b64encode(hashlib.sha1(bytes(sec_key, encoding='utf-8')).digest())
 key_str = str(key)[2:30]
 logging.debug(key_str)

 response = 'HTTP/1.1 101 Switching Protocols\r\n' \
  'Connection: Upgrade\r\n' \
  'Upgrade: websocket\r\n' \
  'Sec-WebSocket-Accept: {0}\r\n' \
  'WebSocket-Protocol: chat\r\n\r\n'.fORMat(key_str)
 conn.send(bytes(response, encoding='utf-8'))
 logging.debug('Send the handshake data')
 WebSocketThread(conn).start()

进行通信

服务端解析 WebSocket 报文

Server 端接收到 Client 发来的报文需要进行解析

Client 包格式

WebSocket中通信过程的示例分析

FIN: 占 1bit

0:不是消息的最后一个分片
1:是消息的最后一个分片

RSV1, RSV2, RSV3:各占 1bit

一般情况下全为 0。当客户端、服务端协商采用 WebSocket 扩展时,这三个标志位可以非
0,且值的含义由扩展进行定义。如果出现非零的值,且并没有采用 WebSocket 扩展,连接出错。

Opcode: 4bit

%x0:表示一个延续帧。当 Opcode 为 0 时,表示本次数据传输采用了数据分片,当前收到的数据帧为其中一个数据分片;
%x1:表示这是一个文本帧(text frame);
%x2:表示这是一个二进制帧(binary frame);
%x3-7:保留的操作代码,用于后续定义的非控制帧;
%x8:表示连接断开;
%x9:表示这是一个心跳请求(ping);
%xA:表示这是一个心跳响应(pong);
%xB-F:保留的操作代码,用于后续定义的控制帧。

Mask: 1bit

表示是否要对数据载荷进行掩码异或操作。
0:否
1:是

Payload length: 7bit or (7 + 16)bit or (7 + 64)bit

表示数据载荷的长度
0~126:数据的长度等于该值;
126:后续 2 个字节代表一个 16 位的无符号整数,该无符号整数的值为数据的长度;
127:后续 8 个字节代表一个 64 位的无符号整数(最高位为 0),该无符号整数的值为数据的长度。

Masking-key: 0 or 4bytes

当 Mask 为 1,则携带了 4 字节的 Masking-key;
当 Mask 为 0,则没有 Masking-key。
掩码算法:按位做循环异或运算,先对该位的索引取模来获得 Masking-key 中对应的值 x,然后对该位与 x 做异或,从而得到真实的 byte 数据。
注意:掩码的作用并不是为了防止数据泄密,而是为了防止早期版本的协议中存在的代理缓存污染攻击(proxy cache poisoning attacks)等问题。

Payload Data: 载荷数据

解析 WebSocket 报文代码如下:

def read_msg(data):
 logging.debug(data)

 msg_len = data[1] & 127 # 数据载荷的长度
 if msg_len == 126:
 mask = data[4:8] # Mask 掩码
 content = data[8:] # 消息内容
 elif msg_len == 127:
 mask = data[10:14]
 content = data[14:]
 else:
 mask = data[2:6]
 content = data[6:]

 raw_str = '' # 解码后的内容
 for i, d in enumerate(content):
 raw_str += chr(d ^ mask[i % 4])
 return raw_str

服务端发送 WebSocket 报文

返回时不携带掩码,所以 Mask 位为 0,再按载荷数据的大小写入长度,最后写入载荷数据。

struct 模块解析

struct.pack(fmt, v1, v2, ...)

按照给定的格式 fmt,把数据封装成字符串 ( 实际上是类似于 C 结构体的字节流 )

struct 中支持的格式如下表:

FormatC Typepython typeStandard size
xpad byteno value
ccharbytes of length 11
bsigned charinteger1
Bunsigned charinteger1
?_Boolbool1
hshortinteger2
Hunsigned shortinteger2
iintinteger4
Iunsigned intinteger4
llonginteger4
Lunsigned longinteger4
qlong longinteger8
Qunsigned long longinteger8
nssize_tinteger
Nsize_tinteger
e-7float2
ffloatfloat4
ddoublefloat8
schar[]bytes
pchar[]bytes
Pvoid *integer

为了同 C 语言中的结构体交换数据,还要考虑有的 C 或 c++ 编译器使用了字节对齐,通常是以 4 个字节为单位的 32 位系统,故而 struct 根据本地机器字节顺序转换。可以用格式中的第一个字符来改变对齐方式,定义如下:

CharacterByte orderSizeAlignment
@nativenativenative
=nativestandardnone
<little-endianstandardnone
>big-endianstandardnone
!network (= big-endian)standardnone

发送 WebSocket 报文代码如下:

def write_msg(message):
 data = struct.pack('B', 129) # 写入第一个字节,10000001

 # 写入包长度
 msg_len = len(message)
 if msg_len <= 125:
  data += struct.pack('B', msg_len)
 elif msg_len <= (2 ** 16 - 1):
  data += struct.pack('!BH', 126, msg_len)
 elif msg_len <= (2 ** 64 - 1):
  data += struct.pack('!BQ', 127, msg_len)
 else:
  logging.error('Message is too long!')
  return

 data += bytes(message, encoding='utf-8') # 写入消息内容
 logging.debug(data)
 return data

以上是“WebSocket中通信过程的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网VUE频道!

--结束END--

本文标题: WebSocket中通信过程的示例分析

本文链接: https://www.lsjlt.com/news/76212.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • WebSocket中通信过程的示例分析
    小编给大家分享一下WebSocket中通信过程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!什么是 WebSocket...
    99+
    2022-10-19
  • Linux中进程通信的示例分析
    这篇文章将为大家详细讲解有关Linux中进程通信的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数...
    99+
    2023-06-27
  • Linux进程通信的示例分析
    这篇文章主要为大家展示了“Linux进程通信的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux进程通信的示例分析”这篇文章吧。linux下的多个进程间的通信机制叫做IPC(,它是...
    99+
    2023-06-28
  • Python中进程间通信的示例分析
    这篇文章给大家分享的是有关Python中进程间通信的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。进程概述进程(Process)是计算机中已运行程序的实体。进程与程序不同,程序本身只是指令、数据及器组织形...
    99+
    2023-06-29
  • WebSocket的示例分析
    这篇文章主要介绍WebSocket的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、Socket简介Socket又称"套接字",应用程序通常通过"套接字"向网络发出请...
    99+
    2023-06-22
  • Socket通信的示例分析
    这篇文章将为大家详细讲解有关Socket通信的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。 建立网络通信...
    99+
    2023-06-27
  • jsp到servlet后台服务通信过程的示例分析
    这篇文章主要介绍了jsp到servlet后台服务通信过程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。web.xml 文件对于任何一个web 运用来说,有,而且只能...
    99+
    2023-06-02
  • WebSocket与实时通信的应用案例分析
    随着互联网的发展和技术的进步,实时通信在各种应用中变得越来越重要。而传统的基于HTTP的请求-响应模式往往无法满足实时通信的需求,因此WebSocket作为一种新的协议应运而生。WebSocket协议基于TCP,允许在客户端和服务器之间建立...
    99+
    2023-10-21
    WebSocket:WebSocket是一种协议 支持实时通信。关键词:WebSocket
  • golang基于websocket通信tcp keepalive实例分析
    本文小编为大家详细介绍“golang基于websocket通信tcp keepalive实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“golang基于websocket通信tcp keepalive实例分析”文...
    99+
    2023-06-30
  • websocket+sockjs+stompjs的示例分析
    这篇文章主要介绍了websocket+sockjs+stompjs的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.http与websockethttp超文本传输协...
    99+
    2023-06-09
  • Vue组件通信的示例分析
    这篇文章主要介绍Vue组件通信的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!实践方法由于更换新的框架,我们的项目由Avalon更新成Vue.但是为了兼容以前的业务代码,不能...
    99+
    2022-10-19
  • C#异步通信的示例分析
    这篇文章主要为大家展示了“C#异步通信的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C#异步通信的示例分析”这篇文章吧。C#异步通信概念及应用的认识首先让我们来看看:在网络编程中运用S...
    99+
    2023-06-17
  • Vue中Axios异步通信的示例分析
    这篇文章将为大家详细讲解有关Vue中Axios异步通信的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。首先我们创建一个.json文件,作为交互使用,我们列举json数据格式模拟传递到前端来帮助小伙...
    99+
    2023-06-25
  • Android下Activity间通信序列化过程中深浅拷贝的示例分析
    这篇文章主要介绍了Android下Activity间通信序列化过程中深浅拷贝的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前言问题的背景是,视频互动业务需要增加弹幕...
    99+
    2023-05-30
    android activity
  • 微信小程序webview与h5通过postMessage实现实时通讯的示例分析
    这篇文章给大家分享的是有关微信小程序webview与h5通过postMessage实现实时通讯的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在做 React Nativ...
    99+
    2022-10-19
  • 小程序websocket心跳库的示例分析
    这篇文章给大家分享的是有关小程序websocket心跳库的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。介绍websocket-heartbeat-miniprogram...
    99+
    2022-10-19
  • golang中vue使用websocket的示例分析
    小编给大家分享一下golang中vue使用websocket的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一. 编写golang服务端导入必要的webs...
    99+
    2023-06-15
  • Angualr组件间通信的示例分析
    这篇文章主要介绍Angualr组件间通信的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Angualr 组件间通信约定: 遵循Angular官方的说法,下文中的Angular...
    99+
    2022-10-19
  • Angularjs中启动过程的示例分析
    这篇文章主要介绍Angularjs中启动过程的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!启动过程(v1.3.9)步骤一用自执行函数的形式让整个代码在加载完成之后立即执行i...
    99+
    2022-10-19
  • mysql中存储过程的示例分析
    这篇文章主要介绍了mysql中存储过程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在mysql中,存储过程是一组为了完成特定功能...
    99+
    2022-10-18
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作