Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

WebSocket协议

20
Sep
2017

WebSocket协议

By Alex
/ in Network
/ tags WebSocket
0 Comments
简介

WebSocket是一种全双工(full-duplex)的双向通信技术,它依赖于单个套接字。使用WebSocket之后,HTTP连接升级为TCP长连接,可以被反复使用以传输数据。WebSocket连接可以在HTTP或者HTTPS之上启动。

WebSocket的出现,让B/S应用的实时性更好,因为服务器可以随时把数据推送到客户端,不需要客户端进行轮询。

WebSocket常常指代一套JavaScript的API,但它也作为一种网络协议(RFC 6455),本文主要探讨WebSocket协议的细节。

协议对比
特性 TCP HTTP WebSocket
寻址方式 IP地址+端口 URL URL
并发传输 全双工 半双工 全双工
载荷格式 二进制流 MIME报文 文本或者二进制消息
消息边界 无 有 有
面向连接 是 否 是

可以看到,WebSocket包含了消息边界规范,因而比TCP更加简单。使用TCP时,随着网络负载、延迟的变化,TCP报文如何分片是无法预测的,唯一的保证是每个字节的接收顺序和发送顺序一致。而使用WebSocket时,多字节的消息会完整、按序的到达。

握手
打开握手

所有WebSocket连接都是在HTTP连接升级产生的。 客户端打开HTTP连接时,发送类似下面的请求:

1
2
3
4
5
6
7
8
9
GET /h264src HTTP/1.1
Pragma: no-cache
Cache-Control: no-cache
Host: 192.168.0.89:9090
Origin: http://192.168.0.89:9090
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: BHIuTA54YKc80CVB9sfaJw==
Sec-WebSocket-Version: 13

此请求与普通HTTP请求没有太大差异,关键的不同就是Upgrade头,其取值为websocket,表示升级当前连接的协议为WebSocket。

如果服务器同意升级,则HTTP应答报文类似下面:

1
2
3
4
5
HTTP/1.1 101
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: gJ0vp6zOXy4g/koag0FAJkBCwSU=
Date: Wed, 20 Sep 2017 03:17:27 GMT

101状态码的含义是切换协议,切换到的协议由Upgrade字段说明。Sec-WebSocket-Accept的取值根据Sec-WebSocket-Key推导,供客户端验证。

关闭握手

WebSocket关闭并不总是能正常进行,特别是在因特网或者其它不可考网络中进行通信的时候,底层TCP连接可能突然就断开。

当正常关闭WebSocket时,关闭行为的发起端发送特定的opcode=8的消息给对方,说明关闭的操作代码和原因。

关闭操作代码和原因作为载荷发送。关闭操作代码为16bit整数,关闭原因则是简短的UTF-8字符串。关闭代码如下表:

关闭代码 说明
1000 Normal Close。正常关闭
1001 Going Away。发起者正在关闭,并且不期望后续再发起连接。出现的原因例如服务器准备停机维护
1002 Protocol Error。因为协议错误而关闭
1003 Unacceptable Data Type。消息类型不支持
1004-1006 保留
1007 Invalid Data。数据无效,例如错误编码的文本消息
1008 Message Violates Policy。如果关闭原因不被其它关闭代码覆盖,或者你不希望暴露关闭原因给对方,使用此代码
1009 Message Too Large。消息长度过大,无法处理
1010 Extension Required。由客户端发送,如果服务器不支持客户端需要的扩展
1011 Unexpected Condition。不可预知的原因导致应用程序无法继续处理连接
1015 TLS Failure。在握手之前TLS处理失败,不要使用此代码
4000-4999 你可以自定义这些代码的用途
报文格式

一旦握手完成,之后的通信均基于WebSocket报文。通信双方可以随时发送WebSocket报文,此所谓全双工。

报文在网络中以二进制形式表示,它包含一个报文头。报文头标记了不同帧(Frame)之间的边界并且包含了简单类型信息。1-N个帧组成完整的WebSocket消息,通常情况下,一个消息总是包含仅仅一个帧,因此,帧和消息这两个术语经常替换使用。

WebSocket帧的格式如下图:

websocket-header

FIN

一般取值0,除非要发送有多个帧组成的消息。

要发送由多个帧组成的消息,则需要把报文首位FIN置为0。依次发送完所有帧后,将FIN置为1,提示接收方所有帧已经发送完毕。 

RSVx

除非协商使用了某种WebSocket扩展,这3bit均设置为0

opcode

指定消息载荷的类型,对应第一字节的后4个bit:

opcode 载荷类型 说明
1 文本 载荷为文本
2 二进制 载荷为字节 
8 关闭连接 客户端或者服务器发起,关闭握手 
9 Ping 客户端或者服务器发起,Ping消息 
10 Pong 客户端或者服务器发起,Pong消息 
掩码

从浏览器发送到服务器的WebSocket帧被掩码处理以混淆载荷内容。掩码的意图并非防止窃听,而是出于非一般性的安全考虑,以及增强和即有HTTP代理服务器的兼容性。

报文头第二字节第1位说明报文是否被掩码处理。WebSocket协议要求客户端对所有帧进行掩码处理,服务器收到的任何帧,都需要解除掩码后再进一步处理。

如果报文被掩码,在报文长度头字段之后,会有4字节的掩码键。

载荷长度

WebSocket使用可变bit数来标注帧的长度:

  1. 如果帧小于126字节,使用7bit标注长度
  2. 如果帧长度在126-216之间, 使用额外两个字节标注长度
  3. 如果帧长度在216以上,使用8字节标注长度

其中,第2、3种情况下,最初的7bit被填写为126或者127,作为指示标记。 

文本消息 

文本消息的编码为UTF-8,此编码与7bit的ASCII兼容。需要注意UTF-8是WebSocket唯一支持的文本编码格式。 

子协议

WebSocket协议支持高层协议、高层协议协商。这些高层协议被称为子协议(Subprotocols)。

要使用子协议,在握手时客户端发送HTTP头 Sec-WebSocket-Protocol,指明它支持的子协议列表。服务器的同名响应头则从列表中选择一个子协议。 

← 基于C/C++的WebSocket库
2017年10月五大道 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • 基于C/C++的WebSocket库
  • Spring对WebSocket的支持
  • SockJS知识集锦
  • 基于Calico的CNI
  • AsyncHttpClient知识集锦

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2