HTTP协议介绍

1. HTTP

        HTTP协议用于客户端和服务端之间的通信,通过请求和响应的交换达成通信。HTTP本身是一种不保存状态的协议,即无状态协议,每当有新请求发送,就会对应着有响应的产生。
        请求报文和响应报文的首部内容由以下数据组成:

        HTTP在传输数据时可以那招数据原貌直接传输,也可以在传输的过程中通过编码提升传输速率。报文 ( $message$ ) 是HTTP通信中的基本单位,由字节流组成;实体 ( $entity$ ) 是请求或响应的有效载荷数据,由实体首部和实体主体组成。通常报文主体等于实体主体,只有当传输中进行编码操作时,实体主体的内容才会发生变化。
        在传输大容量数据时,HTTP允许将数据分割,这种功能称为分块传输编码 ( $Chunked\ \ Transfer\ \ Coding$ ),允许将实体主体分块,每块使用十六进制标记大小,最后一块会使用 $0(CR+LF)$ 标记。为了发送多种类型实体,HTTP还采用了多部份对象集合,包含如下对象:$multipart/form-data$ 、$multipart/byteranges$ 。在使用时,需要在首部字段里加上 $Content-type$ 。
        HTTP通信时,除客户端和服务器以外,还有一些用于通信数据转发的应用程序,例如代理、网关和隧道。

1.1 请求

GET /index.htm HTTP/1.1
Host: xxxx.com

        起始行开头的 $GET$ 表示请求访问服务器的类型,称为方法。$/index.htm$ 是请求访问的资源对象,也叫做请求URI ( $Request\ \ URI$ ) 。最后的 $HTTP/1.1$ 即HTTP版本号,指明客户端使用的HTTP协议版本。
        HTTP使用URI定位互联网上的资源,可以指定完整路径,也可以通过与 $Host$ 字段结合指定相对路径。如果不是访问特定资源而是对服务器本身发起请求,可以使用 $*$ 代替请求URI,如下:

OPTIONS * HTTP/1.1

        HTTP/1.1中可使用的方法如下:

        HTTP/1.1中提供了持久连接 ( $HTTP\ \ Persistence\ \ Connections$ ,也称为 $HTTP\ \ keep-alive$ ),只要任意一端没有明确提出断开连接,则保持TCP连接状态。持久连接使得多数请求以管道化 ( $pipelining$ ) 方式发送称为可能,即不用等待上一个请求的响应即可发送下一个请求。
        作为无状态协议,在登录等场景需要保存状态,因此引入了Cookie技术。Cookie通过在请求和响应报文中写入Cookie信息来控制客户端状态。根据从服务端发送的响应报文内一个叫做 $Set-Cookie$ 的首部字段信息,客户端会保存Cookie,并在下次发送请求时自动在报文中加入Cookie

# 首次请求报文
GET /reader/ HTTP/1.1
Host: xxx.com
# 响应报文
HTTP/1.1 200 OK
Date: Thu, 12 Jul 2012 07:12:20 GMT
Server: Apache
Set-Cookie: sid=1342077140226724; path=/; expires=Wed, 10-Oct-12 07:12:20 GMT
Content-Type: text/plain; charset=UTF-8
# 第二次请求
GET /image/ HTTP/1.1
Host: xxx.com
Cookie: sid=1342077140226724

        内容协商机制是指客户端和服务器端就响应的资源内容进行交涉,然后提供给客户端最为适合的资源。请求报文中的某些首部字段就是判断基准:$Accept$ 、$Accept-Charset$ 、$Accept-Encoding$ 、$Accept-Language$ 、$Content-Language$ 。

1.2 响应

HTTP/1.1 200 OK
Date: Tue, 10 Jul 2012 06:50:15 GMT
Content-Length: 362
Content-Type: text/html

<html>
......

        $HTTP/1.1$ 指明服务器使用的HTTP版本,$200$ 表示请求的处理结果状态码 ( $status\ \ code$ ) 和原因短语 ( $reason-phrase$ ) 。下一行显示了创建响应的日期时间,是首部字段 ( $header\ \ field$ ) 内的一个属性。接下来是以一空行分开的资源实体的主体 ( $entity\ \ body$ )。

1.3 状态码

状态码 类别 原因短语
$1XX$ 信息性状态码 接收的请求正在处理
$2XX$ 成功状态码 请求正常处理完毕
$3XX$ 重定向状态码 需要进行附加操作以完成请求
$4XX$ 客户端错误状态码 服务器无法处理请求
$5XX$ 服务器错误状态码 服务器处理请求出错

        状态码数量繁多,但实际上最常使用的只有 $15$ 种。

状态码 原因
$200\ \ OK$ 从客户端发来的请求被正常处理
$204\ \ No\ \ Content$ 请求成功处理,但响应不包含实体主体,一般在不需要向客户端发送新内容时使用
$206\ \ Partial\ \ Content$ 客户端进行范围请求,响应报文中包含 $Content-Range$ 指定范围的实体内容
$301\ \ Moved\ \ Permanently$ 永久重定向,表示请求的资源已经被分配了新的URI
$302\ \ Found$ 临时重定向,已移动的资源可能还会再改变
$303\ \ See\ \ Other$ 请求资源存在另一个URI,使用 $GET$ 重新获取
$304\ \ Not\ \ Modified$ 所请求的资源未修改,服务器不会返回任何资源
$307\ \ Temporary\ \ Redirect$ 临时重定向,使用 $GET$ 或 $POST$ 获取
$400\ \ Bad\ \ Request$ 请求报文存在语法错误
$401\ \ Unauthorized$ 发送的请求需要有通过HTTP认证的认证信息
$403\ \ Forbidden$ 对请求资源访问被服务器拒绝,服务器没有必要给出详细理由
$404\ \ Not\ \ Found$ 服务器上无法找到请求的资源
$500\ \ Internal\ \ Server\ \ Error$ 服务器端在执行请求时发生错误
$502\ \ Bad\ \ Gateway$ 作为网关或者代理尝试执行请求时从远程服务器接收到一个无效响应
$503\ \ Service\ \ Unavailable$ 服务器暂时处于超负载或者正在进行停机维护

2. HTTPS

        HTTP虽然方便,但也存在不足:使用明文、不验证身份、无法证明报文的完整性。HTTP协议中没有加密机制,但可以通过和SSLTLS的组合使用,加密HTTP的通信内容。与SSL组合使用的HTTP被称为HTTPS ( $HTTP\ \ Secure$ ) 或HTTP over SSLSSL提供了证书,由值得信任的第三方机构颁发,用于证明服务器和客户端是实际存在的。客户端持有证书即可完成个人身份的确认,也可用于对Web网站的认证环节。
        HTTPS并非是应用层的一种新协议,只是通信接口部分用SSLTLS协议代替而已。通常HTTP直接和TCP通信,但当使用SSL时,则演变为先和SSL通信,再由SSLTCP通信。SSL是独立于HTTP的协议,所以除了HTTP外,其他应用层协议如SMTP等也可以配合SSL使用。
        SSL使用一种叫做公开密钥加密 ( $Public-key\ \ cryptography$ ) 的加密处理方式,使用私钥和公钥进行解密和加密。但是公开密钥加密方式还是存在问题,即无法证明公钥本身是公钥。为了解决这个问题,可以使用由数字证书认证机构 ( $CA$ ,$Certificate\ \ Authority$ ) 和其相关机关办法的公钥证书。
        证书还可用于确认服务器背后运营的企业是否存在,即EV SSL证书 ( $Extended\ \ Validation\ \ SSL\ \ Certificate$ )。除此之外,HTTPS中还可以使用客户端证书进行客户端验证,但是存在着获取和发布的问题。

2.1 通信步骤

  1. 客户端发送 $Client\ \ Hello$ 报文开始SSL通信,报文包含SSL版本、随机字符串 $client\ \ random$ 和加密组件列表;
  2. 服务器以 $Server\ \ Hello$ 报文响应,同样包含SSL版本、随机字符串 $server\ \ random$ 和加密组件,服务器的加密组件是从客户端的加密组件中筛选的;
  3. 服务器发送 $Certificate$ 报文,包含公钥证书;
  4. 服务器发送 $Server\ \ Hello\ \ Done$ 报文通知客户端,表示最初阶段的SSL握手协商部分结束;
  5. 第一次SSL握手结束后,客户端以 $Client\ \ Key\ \ Exchange$ 报文回应,包含通信加密中使用的一种称为 $Pre-master\ \ secret$ 的随机密码串,使用公钥加密传输;
  6. 客户端继续发送 $Change\ \ Cipher\ \ Spec$ 报文,提示服务器之后使用 $client\ \ random$ 、$server\ \ random$ 和 $Pre-master\ \ secret$ 密钥加密;
  7. 客户端发送 $Finished$ 报文,包含连接至今全部报文的整体校验值;
  8. 服务器发送 $Change\ \ Cipher\ \ Spec$ 报文;
  9. 服务器发送 $Finished$ 报文;
  10. 在 $Finished$ 报文交换完毕后,SSL连接建立完成,从此开始发送HTTP请求;
  11. 发送HTTP请求和响应;
  12. 客户端断开连接,发送 $close_-notify$ 报文;
  13. 发送 $TCP\ \ FIN$ 关闭TCP通信。

        以上流程中,应用层发送数据时会附加一种叫做MAC ( $Message\ \ Authentication\ \ Code$ ) 的报文摘要,能够查知报文是否被篡改。
        和使用HTTP相比,使用SSL会使网络负载增加 $2$ 到 $100$ 倍,而且加密和解密也会带来额外的处理。

3. 发展

3.1 HTTP1.0/HTTP1.1

        HTTP1.0最早在网页中使用是在 $1996$ 年,那个时候只是使用在一些较为简单的网页和网络请求上,而HTTP1.1在 $1999$ 年才开始广泛应用于现在的各大浏览器网络请求中,也是当前使用最为广泛的HTTP协议。主要区别体现在:

  1. 连接HTTP1.0每次发送请求都要进行一次TCP连接;HTTP1.1新增 $Connection$ 字段,通过设置 $keep-alive$ 保持HTTP连接不断,如果客户端想要关闭连接,可以通过设置 $Connection:false$ 进行关闭;
  2. 传输HTTP1.0规定下一个请求必须在前一个请求响应到达之前才能发送;HTTP1.1引入了管道 ( $pipelining$ ),将多个请求整批提交,并且在发送过程中不需要先等待服务器响应。虽然可以一次性发出所有请求,但是在服务端接收到请求时还是一一处理,如果服务端返回的其中一个响应阻塞,接下来的响应也会被阻塞;
  3. 缓存处理HTTP1.0主要使用 $header$ 里的 $If-Modified-Since$ 和 $Expires$ 来作为缓存判断的标志;HTTP1.1则引入了更多的缓存控制策略如 $If-Unmodified-Since$ 和 $If-Match$ 等;
  4. 带宽优化及网络连接的使用HTTP1.0中不支持分段传输,一次只能传输整个对象;HTTP1.1引入了 $range$ 头,允许只请求资源的某个部分,返回码为 $206$ ;
  5. 错误通知的管理HTTP1.1新增了 $24$ 个错误状态响应码,如 $409$ 和 $410$ 等;
  6. Host头处理HTTP1.0为每台服务器绑定一个唯一的IP地址,因此请求中没有传递 $hostname$ 。但是随着技术发展,一台服务器上可以存在多个虚拟主机,共享IPHTTP1.1支持 $Host$ 头,并且请求中如果没有 $Host$ 头会返回 $400$ 。

3.2 SPDY/HTTP2.0

        SPDYGoogle在 $2012$ 年提出的,是一个综合了HTTPHTTPS协议优点的传输协议。

  1. 降低延迟SPDY使用了多路复用,多个请求共享同一个TCP连接;
  2. 请求优先级:多路复用可能会导致关键请求被阻塞,SPDY允许给请求设置优先级;
  3. 消息头压缩HTTP1.x的消息头很多时候都是重复多余的,通过合适的压缩算法可以减小包大小和数量;
  4. 基于HTTPS的传输:保留HTTPS的加密特性;
  5. 服务端推送:采用了SPDY的网页允许服务端将文件额外推送给客户端。

        SPDY位于HTTP之下,SSL之上,可以兼容老版本HTTP协议,同时可以使用已有的SSL协议。但是SPDY并不是一个标准协议。
        HTTP2.0的特性大部分和SPDY类似,主要有:

  1. 二进制分帧HTTP1.x基于文本解析,文本的表现形式很多,要做到健壮性很难;HTTP2.0HTTPSSL之间增加了一个二进制分帧层,将传输信息分为更小的消息和帧,并采用二进制格式编码;
  2. 多路复用:允许通过单一的HTTP连接发起多重请求,即一个TCP连接上可以有多个请求,即 $stream$ 。每个连接的请求可以随机的混杂在一起,HTTP2.0引入的二进制分帧 ,通过帧对数据进行顺序标识,接收方在接收到数据后可以按照序列对数据进行合并;
  3. 消息头压缩HTTP2.0使用压缩算法减少需要传输的消息头大小,通讯双方各自缓存一份消息头字段表,避免重复数据的传输;
  4. 服务端推送:客户端发送资源请求后,服务器推断客户端需要的其他资源并一同发送给客户端,客户端可以将额外资源放入缓存中。如果客户端已经存在缓存,那么推送就是浪费资源,而且推送提高的性能也不高,大概就几百毫秒,所以只推送CSS是一个比较好的选择;
  5. 主动重置连接:在HTTP1.x中,一个连接同一时间只能发送一个请求,如果需要中止,直接关闭即可;在HTTP2.0中,多个 $stream$ 共享一个连接,如果关闭连接会影响其他 $stream$ ,$RST_-STREAM$ 允许立刻中止一个 $stream$ 。

        HTTP2.0可以说是SPDY的升级版,与SPDY的不同之处在于:

  1. HTTP2.0的消息头压缩算法使用HPACK,而SPDY使用DEFLATE
  2. HTTP2.0初期支持HTTP,而SPDY强制使用HTTPS,后期二者都使用HTTPS

3.3 HTTP3.0

        HTTP3.0也称作 $HTTP\ \ over\ \ QUIC$ ,由Google在 $2015$ 年提出的SPDY v3演化而来的新协议。传统的HTTP协议基于TCPHTTP3.0则基于UDP,并且在UDP的基础上加了一层,即QUIC协议,保证可靠传输,实现了数据重传、拥塞控制等功能。
        HTTP3.0针对HTTP2.0解决了以下问题:

  1. 减少了TCPTLS握手时间HTTP3.0基于UDP,不需要握手。QUIC也需要建立连接,但是在第一个数据包就可以传输数据;
  2. 多路复用丢包时的队头阻塞问题:队头阻塞 ( $Head-of-line\ \ blocking$ ) 指一个数据包阻塞了后续数据包的现象。HTTP2.0的多路复用解决了HTTP层的队头阻塞,但是没有解决TCP层的队头阻塞。QUIC基于UDP实现,解决了队头阻塞的问题;
  3. 前向纠错:前向纠错 ( $Forward\ \ Error\ \ Correction$, $FEC$ ) 是增加数据通讯可信度的方法,在单向通讯信道中,一旦错误被发现,其接收器将无权再次请求传输。QUIC每发送一组数据就对这组数据进行异或计算,并将结果作为一个FEC包发送出去,接收方通过FEC包即可进行校验和纠错;
  4. 流量控制:在多路复用中允许同时存在多个请求 ( $stream$ ),如果有一个请求速度很慢,导致长时间占用缓存,HTTP3.0限制了单一 $stream$ 的缓存大小;
  5. 连接迁移TCP连接基于源IP、源端口、目的IP、目的端口的四元组,当连接发生变化时需要重新建立。HTTP3.0不受四元组影响,当连接发生变化时可以维持该连接,不使用四元组标识,而是使用一个 $64$ 位的随机数,称为 $Connection\ \ ID$ ,对应每个 $stream$ 。

        HTTP3.0建立连接的可以分为首次和非首次两种情况,使用的交换算法是DH ( $Diffie-Hellman$ ) 算法。DH算法的基本过程:

  1. 客户端发送 $client\ \ hello$ 请求;
  2. 服务端生成一个素数 $p$ 和一个整数 $g$ ,以及一个随机数 $K_{s_-pri}$ 作为私钥,然后计算出公钥 $K_{s_-pub} = g^{K_{s_-pri}}\ \ mod\ \ p$ ,服务端将 $K_{s_-pub}$ 、$p$ 和 $g$ 打包称为 $config$ ,发送给客户端;
  3. 客户端随机生成私钥 $K_{c_-pri}$ ,再从 $config$ 中读取 $p$ 和 $g$ ,计算公钥 $K_{c_-pub} = g^{K_{c_-pri}}\ \ mod\ \ p$ ;
  4. 客户端使用私钥 $K_{c_-pri}$ 和服务端发来的 $config$ ,读取服务端公钥 $K_{s_-pub}$ ,生成后续数据加密使用的密钥 $K=K_{s_-pub}^{K_{c_-pri}}\ \ mod\ \ p$ ;
  5. 客户端使用密钥 $K$ 加密,并将公钥 $K_{c_-pub}$ 传递给服务端;
  6. 服务端根据私钥 $K_{s_-pri}$ 和客户端公钥 $K_{c_-pub}$ 生成客户端密钥 $K = K_{c_-pub}^{K_{s_-pri}}\ \ mod\ \ p$ ;
  7. 密钥生成后只会使用一次,后续服务端会使用相同的规则生成公钥和密钥,并使用这组公钥生成新的密钥;

        首次连接生成的 $config$ 会被客户端保存,并在后续连接中使用。$config$ 是有时限的,失效后仍然需要重新生成。

4. 认证

        HTTP/1.1使用的认证方式包括:BASIC认证、DIGEST认证、SSL客户端认证和FormBase认证。

4.1 BASIC认证

  1. 服务器随状态码 $401\ \ Authorization\ \ Required$ 返回带 $WWW-Authenticate$ 首部字段的响应,字段包含认证方式 ( BASIC ) 和Request-URI安全域字符串 ( $realm$ );
  2. 客户端将用户名ID及密码发送给服务器,中间以冒号连接,经过Base64编码处理。
  3. 服务器对信息正确性进行验证。

4.2 DIGEST认证

  1. 服务器随状态码 $401\ \ Authorization\ \ Required$ 返回带 $WWW-Authenticate$ 首部字段的响应,包含质问响应方式所需的临时质询码 ( 随机数,$nonce$ ) 和 $realm$ ;
  2. 客户端返回的响应首部字段 $Authorization$ 内包含 $username$ 、$realm$ 、$nonce$ 、$uri$ 和 $response$ 的字段信息;
  3. 服务器对信息正确性进行验证。

4.3 SSL客户端认证

  1. 服务器发送 $Certificate\ \ Request$ 报文,要求客户端提供证书;
  2. 客户端将证书信息以 $Client\ \ Certificate$ 报文方式发送给服务器;
  3. 服务器验证客户端证书。

4.4 基于表单认证

  1. 客户端将用户ID和密码等信息放入报文的实体部分,通常通过 $POST$ 请求发送给服务器;
  2. 服务器通过Session ID标识用户,并进行身份验证。通常会使用Cookie传输Session ID给客户端;
  3. 客户端接收到Session ID后,将其作为Cookie保存在本地。

5. CORS

        CORS全称 $Cross-Origin\ \ Resource\ \ Sharing$ ,即跨域资源共享,是一种让运行在一个域 ( $Origin$ ) 上的Web应用被准许访问来自不同源服务器上指定资源的机制。Web概念中域的内容由协议、主机和用于访问它的端口定义,当且仅当这三个内容都匹配时,两个对象才有相同域。协议相同、域名相同、端口相同的安全策略也被称为同源策略 ( $Same\ \ Origin\ \ Policy$ )。某些操作仅限于具有相同来源的内容,可以使用CORS取消此限制。
        出于安全的因素,浏览器限制了从脚本发起跨域的HTTP请求。$XMLHttpRequest$ 和其他 $Fetch$ 接口会遵循同源策略。也就是说使用这些API的应用程序想要请求相同的资源,那么他们应该具有相同的来源,除非来自其他来源的响应包括正确的CORS标头。
        跨域资源共享标准通过添加新的HTTP标头来工作,这些标头允许服务器描述哪些来源的可以从Web浏览器读取信息。另外,对于可能导致服务器产生副作用的HTTP请求方法,该规范要求浏览器预检请求,即使用 $OPTIONS$ 请求从服务器请求受支持的方法。

6. Session/Cookie

        HTTP是一种无状态协议,即每次服务端收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录。SessionCookie的主要目的就是为了弥补HTTP的无状态特性。
        客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个对象便是Session对象,Java语言中的结构通常为 $ConcurrentHashMap$ ,服务端可利用Session存储客户端在同一个会话期间的一些操作记录。服务器在第一次接收到请求时,会生成一个 $SessionID$ ,并通过响应头的 $Set-Cookie:\ JSESSIONID=XXXXX$ 命令,向客户端发送要求设置的Cookie响应。客户端接收到响应后,会设置 $JSESSIONID=XXXXX$ 的Cookie信息,该Cookie过期时间为浏览器会话结束时间。Session机制有一个缺点,比如 $A$ 服务器存储了Session,在做了负载均衡后,假设一段时间内 $A$ 的访问量激增,会转发到 $B$ 进行访问,但是 $B$ 并没有存储Session
        Cookie是服务器发送到Web浏览器的一小块数据,浏览器会存储Cookie,并与下一个请求一起发送到服务器。通常用于判断两个请求是否来自同一个浏览器,例如用户保持登录状态。Cookie包括 $Session\ \ Cookie$ 和 $Persistent\ \ Cookie$ , 如果Cookie不包含到期时间,则为会话Cookie,否则为持久性Cookie,在到期指定时间会从磁盘中删除。安全的Cookie需要经过HTTPS协议通过加密的方式发送到服务器,即使是安全的,也不应该将敏感信息存储在Cookie中,因为它们本质上是不安全的。缺少 $HttpOnly$ 属性会导致攻击者可以通过程序获取到用户的Cookie信息,造成用户Cookie信息泄漏。
        JWTSession都可以为网站提供用户的身份认证。在Session Cookie中,用户的登录状态会保存在服务器的内存中,当用户登录时,Session就被服务端安全的创建。每次请求时,服务器都会从Cookie中读取 $SessionID$ ,如果服务端数据和读取的 $SessionID$ 相同,那么服务器就会发送响应给浏览器,允许登录。JWT中存储的信息是经过数字签名的,可以使用HMAC算法或者使用RSA/ECDSA的公用/专用密钥对JWT进行签名。
        JWT是无状态的,因为声明被存储在客户端中,而不是服务端中,身份验证可以在本地进行,而不是在请求必须通过服务器数据库或类似位置中进行。这意味着可以对用户进行多次身份验证,而无需与站点或应用程序的数据库进行通信。由于Session Cookie存储在服务器内存中,会耗费大量资源,而JWT是无状态的,可以节省服务器资源。Session Cookie只能用在单节点域或者它的子域中,如果尝试通过第三个节点访问,就会被禁止,而JWT可以通过多个节点进行用户认证,也就是跨域认证。综上,对于一些中小型网站,如果只需要登录用户访问存储在站点数据库的一些信息,Session Cookie就可以满足需求;对于企业级站点,需要处理大量请求,尤其是大量第三方域的访问,JWT更合适。

7. WebSocket

        WebSocketWeb浏览器与Web服务器之间的全双工通信标准。一旦Web服务器与客户端之间建立起WebSocket协议的通信连接,之后所有的通信都依靠这个专用协议进行,并且可以互相发送任意格式的数据。由于是建立在HTTP基础上的协议,因此连接的发起方仍是客户端,而一旦建立WebSocket通信连接,不论服务器还是客户端,任意一方都可以直接向对方发送报文。
        为了实现WebSocket通信,需要用到HTTP的 $Upgrade$ 首部字段。

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

        $Sec-WebSocket-Key$ 字段内记录着握手过程中必不可少的键值。$Sec-WebSocket-Protocol$ 字段内记录使用的子协议,在连接分开使用时,定义连接的名称。
        对于升级请求,返回 $101\ \ Switching\ \ Protocols$ 响应。

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

        $Sec-WebSocket-Accept$ 字段值是由握手请求中的 $Sec-WebSocket-Key$ 的字段值生成的。在成功握手确立WebSocket连接后,通信时不再使用HTTP的数据帧,而是使用WebSocket独立的数据帧。

HTTP协议介绍