HTTP:协议升级机制(WebSocket) 您所在的位置:网站首页 websocket验证用户 HTTP:协议升级机制(WebSocket)

HTTP:协议升级机制(WebSocket)

2023-11-09 02:37| 来源: 网络整理| 查看: 265

HTTP协议提供了一种特殊的机制,这一机制允许将一个已建立的连接升级成新的、不相容的协议。

通常来说这一机制总是由客户端发起的(不过也有例外,比如说可以由服务端发起升级到传输层安全协议(TLS)),服务端可以选择是否要升级到新协议。借助这一技术,连接可以以常用的协议启动(比如HTTP/1.1),随后再升级到HTTP2甚至是WebSockets.

注意:HTTP/2 明确禁止使用此机制,这个机制只属于HTTP/1.1

升级HTTP/1.1的链接

协议升级请求总是由客户端发起的;暂时没有服务端请求协议更改的机制。当客户端试图升级到一个新的协议时,可以先发送一个普通的请求如GET、POST等,不过这个请求需要进行特殊配置以包含升级请求。

这个请求需要添加两项额外的header:

Connection: Upgrade:设置 Connection 头的值为 “Upgrade” 来指示这是一个升级请求.Upgrade: protocols:Upgrade 头指定一项或多项协议名,按优先级排序,以逗号分隔。

一个典型的包含升级请求的例子差不多是这样的:

GET /index.html HTTP/1.1 Host: www.example.com Connection: upgrade Upgrade: example/1, foo/2

如果服务器没有升级这次连接,它会忽略客户端发送的 Upgrade 头部字段,返回一个常规的响应(例如一个200 OK)

如果服务器决定升级这次连接,就会返回一个 101 Switching Protocols 响应状态码,和一个要切换到的协议的头部字段Upgrade。

HTTP/1.1 101 Switching Protocols Upgrade: foo/2 Connection: Upgrade

服务在发送 101 状态码之后,就可以使用新的协议,并可以根据需要执行任何其他协议指定的握手。实际上,一旦这次升级完成了,连接就变成了双向管道。并且可以通过新协议完成启动升级的请求。

由HTTP/1.1请求建立的连接可以升级为HTTP/2协议的连接,但是反过来不可以。事实上HTTP/2已经不再支持101状态码了,也不再支持任何连接升级机制。

WebSocket

在TCP/IP协议栈的时候有关TCP Socket,它实际上是一种功能接口,通过这些接口就可以使用TCP/IP协议栈在传输层收发数据。

而WebSocket中,“Web”指的就是HTTP,“Socket”是在套接字调用,WebSocket就是运行在Web,也就是HTTP上的Socket通信规范,提供与TCP Socket类似的功能,使用它可以像TCP Socket一样调用下层协议栈,任意的收发数据

更准确的说,WebSocket是一种基于TCP的轻量级网络通信协议,在地位上与HTTP是平级的

为什么要有WebSocket

不过,已经有了HTTP协议,为什么要有WebSocket呢?

其实,WebSocket与HTTP/2一样,都是为了解决HTTP某方面的缺陷而诞生的。

HTTP/2针对的是队头阻塞WebSocket针对的是请求-应答通信模式

那么,“请求-应答”有什么不好的地方吗?

“请求-应答”是一种半双工的通信模式,虽然可以双向收发数据,但是同一时刻只能一个方向上有动作,传输效率低。更关键的一点是,它是一种被动通信模式,服务器只能被动响应客户端的请求,无法主动向客户端发送数据虽然后来的HTTP/2、HTTP/3新增了stream、server push等特性,但“请求-应答”依然是主要的工作模式。这就导致HTTP难以应用在动态页面、即时消息、网络游戏等要求“实时通信”的领域在WebSocket出现之前,在浏览器环境里使用JavaScript开发实时Web应用很麻烦。因为浏览器是一个“受限的沙盒”,不能用TCP,只有HTTP协议可用,所以就出现了很多“变通”的技术,轮询(polling)就是比较常用的一种简单的说,轮询就是不停地向服务器发送HTTP请求,问有没有数据,有数据的话服务器就用响应报文回应。如果轮询的频率比较高,就可以近似实现“实时通信”效果但轮询的缺点也很明显,反复发送无效查询请求耗费了大量的带宽和CPU资源,非常不经济

所以,为了克服 HTTP“请求 - 应答”模式的缺点,WebSocket 就“应运而生”了。它原来是 HTML5 的一部分,后来“自立门户”,形成了一个单独的标准,RFC 文档编号是6455。

WebSocket的特点 WebSocket是一个真正的全双工的通信协议,与TCP一样,客户端和服务器都可以随时向对方发送数据。因此,一旦后台有新的数据,服务器就可以将之推送到客户端,不需要客户端轮询,“实时通信”的概率也就提高了。WebSocket采用了二进制帧结构,语法、语义与HTTP完全不兼容,但因为它的主要运行环境是浏览器,为了便于推广和应用,就不得不“搭便车”,在使用习惯上尽量向HTTP考虑,这就是它名字里的“web”的含义服务发现方面,WebSocket没有使用TCP的“IP地址+端口号”,而是延用了HTTP的URI格式,但开头的协议名不是“http”,引入的是两个新的名字:“ws”和“wss”,分别表示明文和加密的WebSocket协议WebSocket的默认断开也选择了80和443,因为现在互联网上的防火墙屏蔽了绝大多数端口,只对HTTP的80、443端口“放行”,所以WebSocket就可以“伪装”成HTTP协议,比较容易的“穿透”防火墙,与服务器建立连接。

在这里插入图片描述

WebSocket的帧结构

WebSocket用的和HTTP/2一样,用的也是二进制帧。但WebSocket更侧重于“实时通信”,HTTP/2更侧重于提高传输效率,所以两者的帧结构也有很大的区别。

WebSocket虽然有帧,但却没有像HTTP/2那样定义“流”,也就不存在“多路复用”、“优先级”等复杂的特性,而它自身就是“全双工”的,也就不需要“服务器推送”。所以,WebSocket的帧简单一些。

下图就是WebSocket的帧结果定义,长度不固定,最少2个字节,最大14个字节。看起来复杂,实际上很简单。

开头的两个字节是必须的,也是最关键的 第一个字节FIN是消息结束的标志位,相当于HTTP/2里面的END_STREAM,表示数据发送完毕,一个消息可以拆成多个帧,接收方看到FIN之后,就可以把前面的帧拼起来,组成完成的消息FIN后面的三位是保留位,目前没有任何意义,但是必须是0第一个字节后的后4位很重要,叫做Opcode,操作吗,其实就是帧类型,比如1表示帧内容是纯文本,2表示帧内容是二进制数据,8是关闭连接,9和10分别是连接保活的PING和PONG第二个字节的第一位是掩码标志位MASK,表示帧内容是否使用异或操作(xor)做简单的加密。目前的WebSocket标准规定,客户端发送数据必须使用掩码,而服务器发送则必须不使用掩码第二个字节后 7 位是Payload len,表示帧内容的长度。它是另一种变长编码,最少 7位,最多是 7+64 位,也就是额外增加 8 个字节,所以一个 WebSocket 帧最大是2^64。长度字段后面是“Masking-key”,掩码密钥,它是由上面的标志位“MASK”决定的,如果使用掩码就是 4 个字节的随机数,否则就不存在。

这么分析下来,其实 WebSocket 的帧头就四个部分:“结束标志位 + 操作码 + 帧长度 +掩码”,只是使用了变长编码的“小花招”,不像 HTTP/2 定长报文头那么简单明了。

在这里插入图片描述

WebSocket的握手

和TCP、TLS一样,WebSocket也要有一个握手的过程,然后才能正式收发数据。

这里它还是搭上了 HTTP 的“便车”,利用HTTP本身的“协议升级”特性,“伪装”成HTTP,这样就能绕过浏览器沙盒、网络防火墙等限制,这也是 WebSocket 与HTTP 的另一个重要关联点。

如果想要自己重头实现WebSocket 连接,就必须要处理握手和升级过程。

WebSocket 的握手是一个标准的 HTTP GET 请求,但要带上两个协议升级的专用头字段:

“Connection: Upgrade”,表示要求协议“升级”;“Upgrade: websocket”,表示要“升级”成 WebSocket 协议。

在创建初始HTTP/1.1会话之后你需要发送另一个HTTP GET,但在headers中要带上Upgrade (en-US) and Connection,也就是:

Connection: Upgrade Upgrade: websocket

另外,为了防止普通的 HTTP 消息被“意外”识别成 WebSocket,握手消息还增加了两个额外的认证用头字段(所谓的“挑战”,Challenge):

Sec-WebSocket-Key:一个 Base64 编码的 16 字节随机数,作为简单的认证密钥;从本质上说,它表示“是的,我真的想打开一个WebSocket连接。”Sec-WebSocket-Version:协议的版本号,当前必须是 13。

在这里插入图片描述 服务器收到 HTTP 请求报文,看到上面的四个字段,就知道这不是一个普通的 GET 请求,而是 WebSocket 的升级请求,于是就不走普通的 HTTP 处理流程,而是构造一个特殊的“101 Switching Protocols”响应报文,通知客户端,接下来就不用 HTTP 了,全改用WebSocket 协议通信。

WebSocket 的握手响应报文也是有特殊格式的,要用字段“Sec-WebSocket-Accept”验证客户端请求报文,同样也是为了防止误连接。

当服务器愿意初始化WebSocket连接时,在开始握手过程中,服务器的响应消息中包含该消息。它将在响应头中只出现一次。 Sec-WebSocket-Accept: hash 具体的做法是把请求头里“Sec-WebSocket-Key”的值,加上一个专用的 UUID“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,再计算 SHA-1 摘要。 在这里插入图片描述客户端收到响应报文,就可以用同样的算法,比对值是否相等,如果相等,就说明返回的报文确实是刚才握手时连接的服务器,认证成功。

握手完成,后续传输的数据就不再是 HTTP 报文,而是 WebSocket 格式的二进制帧了。 在这里插入图片描述

WebSocket 一些的 headers Sec-WebSocket-Extensions

用于指定一个或者多个请求服务器使用的协议级websocket扩展。允许在一个请求中使用多个Sec-WebSocket-Extension头,它会自动合并到一个头文件。

Sec-WebSocket-Extensions: extensions

extensions:指需要(或支持)的扩展的逗号分隔列表。这些值来自IANA WebSocket 扩展名注册表。带参数的扩展使用分号表示。比如:

Sec-WebSocket-Extensions: superspeed, colormode; depth=16 Sec-WebSocket-Protocol

按优先级排序指定了一个或多个你想要使用的WebSocket协议。服务器将在响应中包含的aSec-WebSocket-Protocol中选择并返回服务器支持的第一个协议。你也可以在头文件中多次使用它;结果与在单个头文件中使用逗号分隔的子协议标识符列表相同。

Sec-WebSocket-Protocol: subprotocols

subprotocols:以逗号分隔的子协议名称列表,按优先顺序排列。子协议可以从IANA WebSocket子协议名称注册表或者可以是客户机和服务器共同理解的自定义名称。

Sec-WebSocket-Version 请求头中 指定客户端希望使用的WebSocket协议版本,以便服务器可以确认其端部是否支持该版本。 Sec-WebSocket-Version: version

version:客户端在与服务器通信时希望使用的WebSocket协议版本。此编号应该是中列出的最新版本IANA WebSocket版本号注册表. WebSocket协议的最新最终版本是版本13。

响应头中 如果服务器不能使用指定版本的WebSocket协议进行通信,它将响应一个错误(比如426 Upgrade Required),该错误包含在其报头Sec-WebSocket-Version中,并以逗号分隔支持的协议版本列表。如果服务器确实支持请求的协议版本,响应中将包含Sec-WebSocket-Version头。 Sec-WebSocket-Version: supportedVersions

supportedVersions:服务器支持的WebSocket协议版本的逗号分隔列表。

总结

浏览器是一个“沙盒”环境,有很多限制,不允许建立TCP连接收发数据,而有了WebSocket,我们就可以在浏览器与服务器直接建立TCP连接,获取更多的自由。

不过自由也是有代价的,WebSocket虽然是在应用层,但是使用方式与TCP Socket差不多,过于“原始”,用户必须自己管理连接、缓存、状态,开发上比HTTP复杂得多,所以是否要在项目中引入WebSocket必须慎重考虑

HTTP 的“请求 - 应答”模式不适合开发“实时通信”应用,效率低,难以实现动态页面,所以出现了 WebSocket;WebSocket是一个“全双工”的通信协议,相当于对TCP做了一层“薄薄的封装”,让它运行在浏览器环境中WebSocket使用兼容HTTP的URI来发现服务,但是定义了新的协议名“ws”和“wss”,端口号也沿用了80和443WebSocket使用了二进制帧,结果比较简单,特殊的地方是有个“掩码”操作,客户端必须掩码,服务器则不用WebSocket利用HTTP协议实现连接握手,发送GET请求要求“协议升级”,握手过程中有个非常简单的认证机制,目的是防止误连接 面试题 WebSocket 你知道工作在哪一层吗?它跟 Socket 有什么区别? websocket是应用层协议socket其实并不是一个协议,它工作在会话层,是为了方便大家直接使用更底层协议(TCP/UDP)而存在的一个抽象层。在设计模式中,它是一个门面模式,把TCP/IP协议族隐藏在socket后面而 WebSocket 则不同,它是一个完整的 应用层协议,包含一套标准的 API 。 SSH 协议你知道它工作在哪一层吗?

应用层协议



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有