(2.1.4.1)刨根问底HTTP与WebSocket的关系
本文整理自简书作者“TheAlchemist”的技术文章,内容有修订。感谢原作者,原文链接在文末。 1、前言本文的上篇《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》介绍了HTTP1.1协议的基本内容,这篇文章将继续分析WebSocket协议,然后对这两个进行简单的比较。 2、系列文章本文是系列文章中的第5篇,本系列文章的大纲如下:
3、更多资料Web端即时通讯新手入门贴: 《新手入门贴:详解Web端即时通讯技术的原理》 Web端即时通讯技术盘点请参见: 《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》 关于Ajax短轮询: 找这方面的资料没什么意义,除非忽悠客户,否则请考虑其它3种方案即可。 有关Comet技术的详细介绍请参见: 《Comet技术详解:基于HTTP长连接的Web端实时通信技术》 《WEB端即时通讯:HTTP长连接、长轮询(long polling)详解》 《WEB端即时通讯:不用WebSocket也一样能搞定消息的即时性》 《开源Comet服务器iComet:支持百万并发的Web端即时通讯方案》 更多WebSocket的详细介绍请参见: 《新手快速入门:WebSocket简明教程》 《理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性》 《八问WebSocket协议:为你快速解答WebSocket热门疑问》 《Socket.IO介绍:支持WebSocket、用于WEB端的即时通讯的框架》 《socket.io和websocket 之间是什么关系?有什么区别?》 《Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?》 有关SSE的详细介绍文章请参见: 《SSE技术详解:一种全新的HTML5服务器推送事件技术》 更多WEB端即时通讯文章请见: http://www.52im.net/forum.php?mod=collection&action=view&ctid=15 4、WebSocket协议WebSocket协议还很年轻,RFC文档(RFC 6455:The WebSocket Protocol)相比HTTP的发布时间也很短,它的诞生是为了创建一种「双向通信」的协议,来作为HTTP协议的一个替代者。那么首先看一下它和HTTP(或者HTTP的长连接)的区别。 如果您对WebSocket协议知之甚少,可以先看看这几篇文章:《WebSocket详解(一):初步认识WebSocket技术》、《WebSocket详解(二):技术原理、代码演示和应用案例》、《WebSocket详解(三):深入WebSocket通信协议细节》。 5、为什么要用WebSocket来替代HTTP上一篇中提到WebSocket的目的就是解决传统Web网络传输中的双向通信的问题,HTTP1.1默认使用持久连接(persistent connection),在一个TCP连接上也可以传输多个Request/Response消息对,但是HTTP的基本模型还是一个Request对应一个Response。 以IM聊天系统为例,客户端要向服务器传送数据,同时服务器也需要实时的向客户端传送信息,一个聊天系统就是典型的双向通信。 要实现Web端双向通信,一般会使用这样几种解决方案:
▲ HTTP的长连接模型 在WebSocket出现之前,传统Web端是如何实现即时通讯的技术的,请参见以下文章: 《Comet技术详解:基于HTTP长连接的Web端实时通信技术》 《WEB端即时通讯:HTTP长连接、长轮询(long polling)详解》 《WEB端即时通讯:不用WebSocket也一样能搞定消息的即时性》 6、WebSocket协议基础WebSocket的目的是取代HTTP在双向通信场景下的使用,而且它的实现方式有些也是基于HTTP的(WS的默认端口是80和443)。现有的网络环境(客户端、服务器、网络中间人、代理等)对HTTP都有很好的支持,所以这样做可以充分利用现有的HTTP的基础设施,有点向下兼容的意味。 简单来讲,WS协议有两部分组成:握手和数据传输。 6.1握手(handshake)出于兼容性的考虑,WS的握手使用HTTP来实现(此文档中提到未来有可能会使用专用的端口和方法来实现握手),客户端的握手消息就是一个「普通的,带有Upgrade头的,HTTP Request消息」。所以这一个小节到内容大部分都来自于RFC2616,这里只是它的一种应用形式,下面是RFC6455文档中给出的一个客户端握手消息示例:
可以看到,前两行跟HTTP的Request的起始行一模一样,而真正在WS的握手过程中起到作用的是下面几个header域:
如果服务器接受了这个请求,可能会发送如下这样的返回信息,这是一个标准的HTTP的Response消息。101表示服务器收到了客户端切换协议的请求,并且同意切换到此协议。 RFC2616规定只有切换到的协议「比HTTP1.1更好」的时候才能同意切换:
6.2WebSocket协议Uriws协议默认使用80端口,wss协议默认使用443端口:
6.3在客户端发送握手之前要做的一些小事在握手之前,客户端首先要先建立连接,一个客户端对于一个相同的目标地址(通常是域名或者IP地址,不是资源地址)同一时刻只能有一个处于CONNECTING状态(就是正在建立连接)的连接。 从建立连接到发送握手消息这个过程大致是这样的:
如果上一步中的TCP连接建立失败,则此WebSocket连接失败。如果协议是wss,则在上一步建立的TCP连接之上,使用TSL发送握手信息。如果失败,则此WebSocket连接失败;如果成功,则以后的所有数据都要通过此TSL通道进行发送。 6.4对于客户端握手信息的一些小要求客户端握手信息的要求:
6.5在客户端接收到Response握手消息之后要做的一些事情接收到Response握手消息之后:
6.6服务端的概念服务端指的是所有参与处理WebSocket消息的基础设施,比如如果某服务器使用Nginx(A)来处理WebSocket,然后把处理后的消息传给响应的服务器(B),那么A和B都是这里要讨论的服务端的范畴。 6.7接受了客户端的连接请求,服务端要做的一些事情如果请求是HTTPS,则首先要使用TLS进行握手,如果失败,则关闭连接,如果成功,则之后的数据都通过此通道进行发送。 之后服务端可以进行一些客户端验证步骤(包括对客户端header域的验证),如果需要,则按照RFC2616来进行错误码的返回。 如果一切都成功,则返回成功的Response握手消息。 6.8服务端发送的成功的Response握手此握手消息是一个标准的HTTP Response消息,同时它包含了以下几个部分:
一旦这个握手发出去,服务端就认为此WebSocket连接已经建立成功,处于OPEN状态。它就可以开始发送数据了。 6.9WebSocket的一些扩展Sec-WebSocket-Version可以被通信双方用来支持更多的协议的扩展,RFC6455中定义的值为13,WebSocket的客户端和服务端可能回自定义更多的版本号来支持更多的功能。其使用方法如上文所述。 6.10发送数据WebSocket中所有发送的数据使用帧的形式发送。客户端发送的数据帧都要经过掩码处理,服务端发送的所有数据帧都不能经过掩码处理。否则对方需要发送关闭帧。 一个帧包含一个帧类型的标识码,一个负载长度,和负载。负载包括扩展内容和应用内容。 6.11帧类型帧类型是由一个4位长的叫Opcode的值表示,任何WebSocket的通信方收到一个位置的帧类型,都要以连接失败的方式断开此连接。 RFC6455中定义的帧类型如下所示:
6.12帧的格式具体的每一项代表什么意思在这里就不做详细的阐述了。 6.12小结一下以上说了这么多,其实Http和WebSocket的关系通过下图就能简单的理解了: 7、与HTTP比较同样作为应用层的协议,WebSocket在现代的软件开发中被越来越多的实践,和HTTP有很多相似的地方,这里将它们简单的做一个纯个人、非权威的比较。 7.1相同点
7.2不同点
(原文链接:http://www.jianshu.com/p/f666da1b1835) |