웹 프론트엔드 JS 튜토리얼 WebSocket 통신 사용량 분석

WebSocket 통신 사용량 분석

May 14, 2018 pm 02:32 PM
web websocket 분석하다

이번에는 WebSocket 통신 사용 분석을 가져왔습니다. WebSocket 통신 사용 분석의 주의사항은 무엇인가요?

WebSocket이란 무엇인가요?

WebSocket은 클라이언트와 서버 간의 양방향 데이터 전송을 위한 표준 프로토콜입니다. 그러나 이는 HTTP와는 아무런 관련이 없습니다. TCP 기반의 독립적인 구현입니다.

과거에는 클라이언트가 서버의 처리 진행 상황을 알고 싶다면 지속적으로 Ajax를 사용하여 폴링해야 했고, 브라우저가 몇 초마다 서버에 요청을 보내도록 해야 했기 때문에 클라이언트에 많은 부담이 가해졌습니다. 섬기는 사람. 또 다른 종류의 폴링은 전화 통화와 유사한 긴 폴링을 사용하는 것입니다. 즉, 클라이언트가 연결을 시작한 후 메시지가 없으면 응답이 끊어지지 않습니다. 클라이언트에 반환되지 않으면 연결 단계가 항상 차단됩니다.

그리고 WebSocket은 이러한 HTTP 문제를 해결합니다. 서버가 프로토콜 업그레이드(HTTP -> WebSocket)를 완료한 후 서버는 클라이언트에 정보를 적극적으로 푸시하여 폴링으로 인해 발생하는 동기화 지연 문제를 해결할 수 있습니다. WebSocket에는 단 한 번의 HTTP 핸드셰이크만 필요하므로 연결이 닫힐 때까지 서버는 클라이언트와 계속 통신할 수 있습니다. 이렇게 하면 서버가 HTTP 프로토콜을 반복적으로 구문 분석할 필요가 없어져 리소스 오버헤드가 줄어듭니다.

새로운 표준의 발전으로 WebSocket은 더욱 성숙해졌으며 다양한 주류 브라우저는 WebSocket에 대한 더 나은 지원을 제공합니다(IE 하위 버전, IE 10 이하와 호환되지 않음). 시간.

WebSocket을 사용할 때, js는 ws 프로토콜을 지원하는데, 이는 가볍게 캡슐화된 Socket 프로토콜과 비슷하지만, 예전에는 Socket 연결을 직접 유지해야 했습니다. 이제 좀 더 표준적인 방식으로 이를 수행할 수 있습니다.

위 그림을 바탕으로 WebSocket의 통신 과정에 대해 자세히 이야기해 보겠습니다.

연결 설정

클라이언트 요청 메시지 헤더

클라이언트 요청 메시지:

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-Version 헤더를 반환해야 합니다.

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>
로그인 후 복사

서버 응답 메시지 헤더

먼저, 다음을 살펴보겠습니다. 서버 응답 메시지:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
로그인 후 복사

한 줄씩 설명하겠습니다

  • 우선 101 상태 코드는 서버가 클라이언트의 요청을 이해했으며 클라이언트에게 다른 프로토콜을 사용하여 요청을 완료하도록 알릴 것임을 나타냅니다. 업그레이드 메시지 헤더

  • 그런 다음 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 包格式

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 中支持的格式如下表:

Format C Type Python type Standard size
x pad byte no value
c char bytes of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
i int integer 4
I unsigned int integer 4
l long integer 4
L unsigned long integer 4
q long long integer 8
Q unsigned long long integer 8
n ssize_t integer
N size_t integer
e -7 float 2
f float float 4
d double float 8
s char[] bytes
p char[] bytes
P void * integer

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

Character Byte order Size Alignment
@ native native native
= native standard none
<little-endianstandardnone
> big-endian standard none
! network (= big-endian) standard none

发送 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 一样实现全双工传输的技术了,迄今为止,大部分开发者还是使用 Ajax 轮询来实现,但这是个不太优雅的解决办法,WebSocket 虽然用的人不多,可能是因为协议刚出来的时候有安全性的问题以及兼容的浏览器比较少,但现在都有解决。如果你有这些需求可以考虑使用 WebSocket:

  • 多个用户之间进行交互;

  • 需要频繁地向服务端请求更新数据。

比如弹幕、消息订阅、多玩家游戏、协同编辑、股票基金实时报价、视频会议、在线教育等需要高实时的场景。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

ES6实现全屏滚动插件步骤详解

Vue中watch使用方法总结

위 내용은 WebSocket 통신 사용량 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

PHP와 WebSocket을 사용하여 실시간 통신을 구현하는 방법 PHP와 WebSocket을 사용하여 실시간 통신을 구현하는 방법 Dec 17, 2023 pm 10:24 PM

인터넷 기술의 지속적인 발전으로 실시간 커뮤니케이션은 일상생활에서 없어서는 안 될 부분이 되었습니다. WebSockets 기술을 사용하면 효율적이고 지연 시간이 짧은 실시간 통신이 가능하며, 인터넷 분야에서 가장 널리 사용되는 개발 언어 중 하나인 PHP도 해당 WebSocket 지원을 제공합니다. 이 기사에서는 PHP와 WebSocket을 사용하여 실시간 통신을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. WebSocket이란 무엇입니까?

PHP 및 WebSocket: 실시간 데이터 전송 모범 사례 PHP 및 WebSocket: 실시간 데이터 전송 모범 사례 Dec 18, 2023 pm 02:10 PM

PHP 및 WebSocket: 실시간 데이터 전송을 위한 모범 사례 방법 소개: 웹 애플리케이션 개발에서 실시간 데이터 전송은 매우 중요한 기술 요구 사항입니다. 기존 HTTP 프로토콜은 요청-응답 모델 프로토콜이므로 실시간 데이터 전송을 효과적으로 달성할 수 없습니다. 실시간 데이터 전송 요구를 충족하기 위해 WebSocket 프로토콜이 탄생했습니다. WebSocket은 단일 TCP 연결을 통해 전이중 통신 방법을 제공하는 전이중 통신 프로토콜입니다. H에 비해

Java 및 WebSocket을 사용하여 실시간 주식 시세 푸시를 구현하는 방법 Java 및 WebSocket을 사용하여 실시간 주식 시세 푸시를 구현하는 방법 Dec 17, 2023 pm 09:15 PM

Java 및 WebSocket을 사용하여 실시간 주식 시세 푸시를 구현하는 방법 소개: 인터넷의 급속한 발전으로 인해 실시간 주식 시세 푸시는 투자자들의 초점 중 하나가 되었습니다. 전통적인 주식시장 푸시 방식은 지연 시간이 길고 새로 고침 속도가 느린 등의 문제가 있으며, 투자자에게는 최신 주식 시장 정보를 적시에 얻을 수 없어 투자 결정에 오류가 발생할 수 있습니다. Java와 WebSocket을 기반으로 한 실시간 주식 시세 푸시는 이러한 문제를 효과적으로 해결하여 투자자가 최신 주가 정보를 최대한 빨리 얻을 수 있도록 해줍니다.

Java Websocket은 온라인 화이트보드 기능을 어떻게 구현합니까? Java Websocket은 온라인 화이트보드 기능을 어떻게 구현합니까? Dec 17, 2023 pm 10:58 PM

JavaWebsocket은 온라인 화이트보드 기능을 어떻게 구현합니까? 현대 인터넷 시대에 사람들은 실시간 협업과 상호작용 경험에 점점 더 많은 관심을 기울이고 있습니다. 온라인 화이트보드는 Websocket을 기반으로 구현된 기능으로, 여러 사용자가 실시간으로 협업하여 동일한 도면판을 편집하고 도면, 주석 등의 작업을 완료할 수 있는 편리한 솔루션을 제공합니다. 다른 시나리오. 1. 기술적 배경 WebSocket은 HTML5에서 제공하는 새로운 프로토콜을 구현합니다.

SSE 및 웹소켓 SSE 및 웹소켓 Apr 17, 2024 pm 02:18 PM

이 기사에서는 데이터를 전달하는 안정적인 방법인 SSE(Server Sent Events)와 WebSocket을 비교해 보겠습니다. 통신 방향, 기본 프로토콜, 보안, 사용 용이성, 성능, 메시지 구조, 사용 용이성, 테스트 도구 등 8가지 측면에서 분석합니다. 이러한 측면을 비교하면 다음과 같이 요약됩니다. 범주 서버 전송 이벤트(SSE) WebSocket 통신 방향 단방향 양방향 기본 프로토콜 HTTP WebSocket 프로토콜 보안 HTTP와 동일 기존 보안 취약점 사용 편의성 설정 간단한 설정 복잡한 성능 빠른 메시지 전송 속도 메시지 처리 및 연결 관리에 영향을 받음 메시지 구조 일반 텍스트 또는 바이너리 사용 용이성 널리 사용 가능 WebSocket 통합에 도움이 됨

golang WebSocket 프로그래밍 팁: 동시 연결 처리 golang WebSocket 프로그래밍 팁: 동시 연결 처리 Dec 18, 2023 am 10:54 AM

Golang은 강력한 프로그래밍 언어이며 WebSocket 프로그래밍에서의 Golang 사용은 개발자들 사이에서 점점 더 가치가 높아지고 있습니다. WebSocket은 클라이언트와 서버 간의 양방향 통신을 허용하는 TCP 기반 프로토콜입니다. 이 기사에서는 Golang을 사용하여 동시에 여러 동시 연결을 처리하는 효율적인 WebSocket 서버를 작성하는 방법을 소개합니다. 기술을 소개하기 전에 먼저 WebSocket이 무엇인지 알아보겠습니다. WebSocket웹 소개

golang에서 파일 전송을 위해 WebSocket을 사용하는 방법 golang에서 파일 전송을 위해 WebSocket을 사용하는 방법 Dec 18, 2023 am 09:06 AM

golang에서 파일 전송을 위해 WebSocket을 사용하는 방법 WebSocket은 양방향 통신을 지원하고 브라우저와 서버 간에 지속적인 연결을 설정할 수 있는 네트워크 프로토콜입니다. golang에서는 타사 라이브러리 gorilla/websocket을 사용하여 WebSocket 기능을 구현할 수 있습니다. 이 기사에서는 파일 전송을 위해 golang 및 gorilla/websocket 라이브러리를 사용하는 방법을 소개합니다. 먼저 고릴라를 설치해야 합니다.

실시간 번역 기능 구현을 위한 PHP Websocket 개발 가이드 실시간 번역 기능 구현을 위한 PHP Websocket 개발 가이드 Dec 18, 2023 pm 05:52 PM

PHP 웹소켓 개발 가이드: 실시간 번역 기능 구현 소개: 인터넷이 발전하면서 다양한 애플리케이션 시나리오에서 실시간 통신이 점점 더 중요해지고 있습니다. 새롭게 떠오르는 통신 프로토콜인 Websocket은 실시간 통신을 훌륭하게 지원합니다. 이 기사에서는 PHP를 사용하여 Websocket 애플리케이션을 개발하는 방법과 실시간 번역 기능을 결합하여 특정 애플리케이션을 시연하는 방법에 대해 자세히 설명합니다. 1. 웹소켓 프로토콜이란 무엇입니까? 웹소켓 프로토콜은

See all articles