Websocket协议之握手链接

Websocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通讯的问题而设计的,是彻底意义上的Web应用端的双向通讯技术,能够取代以前使用半双工HTTP协议而模拟全双工通讯,同时克服了带宽和访问速度等的诸多问题。协议定义为ws和wss协议,分别为普通请求和基于SSL的安全传输,占用端口与http协议系统,ws为80端口,wss为443端口,这样能够支持HTTP代理。web

协议包含两个部分,第一个是“握手”,第二个是数据传输。浏览器

1、Websocket URI

定义的两个协议框架ws和wss与http相似,并且各自部分的要求也是在HTTP协议中使用的同样,各自的URI以下:安全

ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
        wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]服务器

其中port是可选项,query前接“?”。websocket

2、握手(Opening & Closing Handshake)打开链接

当创建一个Websocket链接时,为了保持基于HTTP协议的服务器软件和中间件进行兼容工做,客户端打开一个链接时使用与HTTP链接的同一个端口到服务器进行链接,这样被设计为一个升级的HTTP请求。网络

一、发送握手请求

此时的链接状态是CONNECTING,客户端须要提供host、port、resource-name和一个是不是安全链接的标记,也就是一个WebSocket URI。框架

客户端发送的一个到服务器端握手请求以下:socket

 

        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


这个升级的HTTP请求头中的字段顺序是能够随便的。与普通HTTP请求相比多了一些字段。加密

  • Sec-WebSocket-Protocol:字段表示客户端能够接受的子协议类型,也就是在Websocket协议上的应用层协议类型。上面能够看到客户端支持chat和superchat两个应用层协议,当服务器接受到这个字段后要从中选出一个协议返回给客户端。
  • Upgrade:告诉服务器这个HTTP链接是升级的Websocket链接。
  • Connection:告知服务器当前请求链接是升级的。
  • Origin:该字段是用来防止客户端浏览器使用脚本进行未受权的跨源攻击,这个字段在WebSocket协议中很是重要。服务器要根据这个字段判断是否接受客户端的Socket链接。能够返回一个HTTP错误状态码来拒绝链接。
  • Sec-WebSocket-Key:为了表示服务器赞成和客户端进行Socket链接,服务器端须要使用客户端发送的这个Key进行校验,而后返回一个校验过的字符串给客户端,客户端验证经过后才能正式创建Socket链接。服务器验证方法是:首先进行 Key + 全局惟一标示符(GUID)“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”链接起来,而后将链接起来的字符串使用SHA-1哈希加密,再进行base64加密,将获得的字符串返回给客户端做为握手依据。其中GUID是一个对于不识别WebSocket的网络端点不可能使用的字符串。
发送请求的要求:
  • 请求的WebSocket URI必需要是定义的有效的URI。
  • 若是客户端已经有一个WebSocket链接到远程服务器端,不管是否是同一个服务器,客户端必需要等待上一个链接关闭后才能发送新的链接请求,也就是同一客户端一次只能存在一个WebSocket链接。若是想同一个服务器有多个链接,客户端必需要串行化进行。若是客户端检测到多个到不一样服务器的链接,应该限制一个最大链接数,在web浏览器中应该设定最多能够打开的标签页的数目。这样能够防止到远程服务器的DDOS攻击,但这是对到多个服务器的链接,若是是到同一个服务器链接,并无数目限制。
  • 若是使用了代理服务器,那么客户端创建链接的时候须要告知代理服务器向目标服务器打开TCP链接。
  • 若是链接没有打开,必定是某一方出现错误,此时客户端必需要关闭再次链接的尝试。
  • 链接创建后,握手必需要是一个有效的HTTP请求
  • 请求的方式必须是GET,HTTP协议的版本至少是1.1
  • Upgrade字段必须包含并且必须是"websocket",Connection字段必须内容必须是“Upgrade”
  • Sec-Websocket-Version必须,并且必须是13

二、返回握手应答

服务器返回正确的相应头后,客户端验证后将创建链接,此时状态为OPEN。服务器响应头以下:
        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        Sec-WebSocket-Protocol: chat
响应头握手过程当中是服务器返回的是否赞成握手的依据。
  • 首行返回的是HTTP/1.1协议版本和状态码101,表示变换协议(Switching Protocol)
  • Upgrade 和 Connection:这两个字段是服务器返回的告知客户端赞成使用升级并使用websocket协议,用来完善HTTP升级响应
  • Sec-WebSocket-Accept:服务器端将加密处理后的握手Key经过这个字段返回给客户端表示服务器赞成握手创建链接。
  • Sec-Websocket-Procotol:服务器选择的一个应用层协议。
上述响应头字段被客户端浏览器解析,若是验证到Sec-WebSocket-Accept字段的信息符合要求就会创建链接,同时就能够发送WebSocket的数据帧了。若是该字段不符合要求或者为空或者HTTP状态码不为101,就不会创建链接。
服务器端响应步骤:
  • 解析握手请求头:获取握手依据Key并进行处理,检测HTTP的GET请求和版本是否准确,Host字段是否有权限,Upgrade字段中websocket是一个与大小写无关的ASCII字符串,Connection字段是一个大小写无关的"Upgrade"ASCII字符串,Websocket协议版本必须为13,其余的关于Origin、Protocol和Extensions可选。
  • 发送握手响应头:检测是不是wss协议链接,若是是就是用TLS握手链接,不然就是普通链接。服务器能够添加额外的验证信息到客户端进行验证。当进行一系列验证以后,服务器必须返回一个有效的HTTP响应头。响应头中每一行一个字段,结束必须为“\r\n”,使用的ABNF语法。
除了上述必要头字段以外,其余的HTTP协议定义的字段均可以使用,如Set-Cookie等。
相关文章
相关标签/搜索