WebSocket简绍及使用

WebSocket是一种计算机通信协议,通过单个TCP连接提供全双工(full-duplex)通信信道。 WebSocket协议在2011年由IETF标准化为rfc6455成为国际标准。
WebSocket最大特点就是:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,属于服务器推送技术的一种。
WebSocket旨在在Web浏览器和Web服务器中实现,但可以由任何客户端或服务器应用程序使用。 WebSocket协议是独立的基于TCP的协议。它与HTTP的唯一关系是它的握手被HTTP服务器解释为升级请求。
WebSocket协议支持浏览器和Web服务器之间的交互,具有较低的开销,便于从服务器进行实时数据传输。这可以通过提供标准化的方式使服务器主动将内容发送到浏览器而不被客户端请求获取数据,并允许在保持连接打开的同时传递消息。以这种方式,可以在浏览器和服务器之间进行双向通信。通信通过TCP端口号80(在TLS加密连接的情况下为443)完成,这是因为根据经验证据,大多数防火墙仅允许传出连接到端口80和443的, 因此WebSocket在这种环境下是非常有益的。
大多数主要浏览器(包括Google Chrome,Microsoft Edge,Internet Explorer,Firefox,Safari和Opera)都支持WebSocket协议。 WebSocket还需要服务器上的Web应用程序来支持它。

为什么需要WebSocket

对于HTTP来说,通信或者说请求,只能由Client端发起,也就是单向的,HTTP做不到Server端主动给Client端push消息,而且一般我们为了解决这种单向通信的问题,都会采用client轮询的方式。但是轮询的效率比较低,而且较浪费资源(要么每次都重新打开连接,要么使用http长连接),而WebSocket就是为了解决这个问题的。

WebSocket特点

  • 建立在 TCP 协议之上,服务器端的实现比较容易
  • 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器
  • 数据格式比较轻量,性能开销小,通信高效
  • 可以发送文本,也可以发送二进制数据
  • 没有同源限制,客户端可以与任意服务器通
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL,比如:ws://example.com:80/some/path

WebSocket vs HTTP

http://www.ruanyifeng.com/blogimg/asset/2017/bg2017051502.png
http://www.ruanyifeng.com/blogimg/asset/2017/bg2017051503.jpg

握手协议(Protocol handshake)

要建立一个WebSocket连接,客户端发送一个WebSocket握手请求,服务器返回一个WebSocket握手响应,如下面的例子所示。
Client端请求(就像在HTTP中,每行以\r\n结尾,结尾处必须有一个空白行):

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

Server端响应

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

握手类似于HTTP,允许服务器处理同一端口上的HTTP连接以及WebSocket连接。一旦建立连接,通信将切换到不符合HTTP协议的双向二进制协议。
除了升级headers之外,客户端还会发送一个包含base64编码的随机字节的Sec-WebSocket-Key头,并且服务器使用Sec-WebSocket-Accept头中的密钥散列进行回复。这是为了防止缓存代理(caching proxy f)重新发送先前的WebSocket会话,并且不提供任何身份验证,隐私或完整性。散列函数将固定字符串258EAFA5-E914-47DA-95CA-C5AB0DC85B11(一个GUID)附加到Sec-WebSocket-Key头(未从base64解码)的值,然后应用SHA-1散列函数,并对结果使用base64。
建立连接后,客户端和服务器可以全双工模式来回发送WebSocket数据或文本帧。WebSocket传输被描述为“消息”,其中单个消息可以可选地在多个数据帧之间分割。这可以允许发送初始数据可用的消息,但是消息的完整长度是未知的(它发送一个数据帧,直到到达结束并且被标记为FIN位)。
在服务器端的连接建立过程(针对预期的来源),验证“起始”头是重要的(以防止跨站点WebSocket劫持攻击),这可能是当连接使用Cookie进行身份验证或HTTP身份验证。当敏感(私有)数据通过WebSocket传输时,最好使用Token或类似的保护机制来验证WebSocket连接。
关于握手这块,强烈推荐大家看一下参考资料https://trac.ietf.org/trac/hybi/wiki/FAQ,这样就可以理解为啥这么设计了

为什么是258EAFA5-E914-47DA-95CA-C5AB0DC85B11

258EAFA5-E914-47DA-95CA-C5AB0DC85B11是一个GUID,至于为啥这个没有原因,不过这个值是唯一的而且不会被其他的协议使用。官方回答:Whatis258EAFA5-E914-47DA-95CA-C5AB0DC85B11

为什么是GET方法

简单的说就是最开始的作者用的是GET方法,也就一直没有变化,虽然有一些人提建议不想用GET方法,但是最后因为其他的http method也各有各的问题,而且GET方法流传 已久,大家也就继续使用GET了。官方回答:WhythemethodisGET

Sec-WebSocket-Key 和 Sec-WebSocket-Accept 干啥用的

这个是WebSockets的一个安全策略,通过让client发送一个encoded的随机值,并且server给个对应的响应,这样client就可以确认他们正在和WebSocket server通信,而不是和其他的server通信。
这种设计也有一个有意思的是,他可以促使server端的实现者注意握手期间的信息。因为很多server已经被实现为默认收到的东西就是http的,这会导致一些安全问题或者其他问题。因此通过增加这两个header,server最起码需要从client发送的header中解析出Sec-WebSocket-Key的值。 官方回答:WhatSec-WebSocket-KeyandSec-WebSocket-Acceptarefor

WebSocket使用

TODO 2017-07-06 10:57:30

Spring & WebSocket

TODO 2017-07-06 10:57:30

参考资料

本文版权归作者所有,禁止一切形式的转载,复制等操作
赞赏

微信赞赏支付宝赞赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注