WebSocket是一种比较新的协议,它是伴随着html5规范而生的,虽然还比较年轻,但大多主流浏览器都已经支持。它使用方面、应用普遍,已经渗透到先后端开发的各类场景中。javascript
对http一问一答中二式流程(就是从所周之的“长轮询”技要啦)的不满,催生了支持双向通讯的WebSocket诞生。WebSocket是个不太干净协议。php
本文将从8个常见的疑问入手,为还不了解WebSocket协议的开发者快速普及相关知识,从而节省您学习WebSocket的时间。html
另外,若是您对Web端的即时通信技术还彻底不了解,那么《新手入门贴:详解Web端即时通信技术的原理》、《Web端即时通信技术盘点:短轮询、Comet、Websocket、SSE》这两篇文章请您务必抽时间读一读。html5
学习交流:java
- 即时通信/推送技术开发交流4群:101279154[推荐]nginx
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》git
(本文同步发布于:http://www.52im.net/thread-2488-1-1.html)github
Web端即时通信新手入门贴:
《 新手入门贴:详解Web端即时通信技术的原理》
Web端即时通信技术盘点请参见:
《 Web端即时通信技术盘点:短轮询、Comet、Websocket、SSE》
关于Ajax短轮询:
找这方面的资料没什么意义,除非忽悠客户,不然请考虑其它3种方案便可。
有关Comet技术的详细介绍请参见:
《 Comet技术详解:基于HTTP长链接的Web端实时通讯技术》
《 WEB端即时通信:HTTP长链接、长轮询(long polling)详解》
《 WEB端即时通信:不用WebSocket也同样能搞定消息的即时性》
《 开源Comet服务器iComet:支持百万并发的Web端即时通信方案》
更多WebSocket的详细介绍请参见:
《 新手快速入门:WebSocket简明教程》
《 Socket.IO介绍:支持WebSocket、用于WEB端的即时通信的框架》
《 socket.io和websocket 之间是什么关系?有什么区别?》
有关SSE的详细介绍文章请参见:
《 SSE技术详解:一种全新的HTML5服务器推送事件技术》
更多WEB端即时通信文章请见:
http://www.52im.net/forum.php?mod=collection&action=view&ctid=15
不是。目前此协议的受众的也不只仅是web开发者。web
WebSocket只是一种协议,它和http协议同样,使用相似okhttp的组件,能够在任何地方进行调用,甚至能够借助WebSocket实现RPC框架。chrome
WebSocket和http同样,都是处于OSI模型中的最高层:应用层。
WebSocket借助http协议进行握手,握手成功后,就会变身为TCP通道,今后与http再也不相见。
使用netstat或者ss,可以看到对应的链接,它与处于抽象层的socket,在外观上没有区别。
更多WebSocket和HTTP的关系,以及与Socket的区别,可进一步阅读如下文章:
《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》
长轮询,就是客户端发送一个请求,服务端将一直在这个链接上等待(固然有一个超长的超时时间),直到有数据才返回,它依然是一个一问一答的模式。好比著名的comted。
WebSocket在握手成功后,就是全双工的TCP通道,数据能够主动从服务端发送到客户端,处于连接两端的应用没有任何区别。
WebSocket建立的链接和Http的长链接是不同的。因为Http长链接底层依然是Http协议,因此它仍是一问一答,只是Hold住了一条命长点的链接而已。
长轮询和Http长链接是阻塞的I/O,但WebSocket能够是非阻塞的(具体是多路复用)。
这方面更深刻的资料,请进一步学习:
WebSocket的链接建立是借助Http协议进行的。这样设计主要是考虑兼容性,在浏览器中就能够很方便的发起请求,看起来比较具备迷惑性。
下图是一个典型的由浏览器发起的ws请求,能够看到和http请求长的是很是类似的。
可是,它只是请求阶段长得像而已:
请求的地址,通常是:ws://\*\*\*,或者是使用了SSL/TLS加密的安全协议wss:,用来标识是WebSocket请求。
1)首先,经过Http头里面的Upgrade域,请求进行协议转换。若是服务端支持的话,就能够切换到WebSocket协议。简单点讲:链接已经在那了,经过握手切换成ws协议,就是切换了链接的一个状态而已。
2)Connection域能够认为是与Upgrade域配对的头信息。像nginx等代理服务器,是要先处理Connection,而后再发起协议转换的。
3)Sec-WebSocket-Key 是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。如此操做,能够尽可能避免普通 HTTP 请求被误认为 WebSocket 协议。
其余的,像Sec-WebSocket*字样的头信息,代表了客户端支持的子协议以及其余信息。像loT中很流行的mqtt,就能够做为WebSocket的子协议。
使用javascript,能够很容易链接一个WebSocket服务端:
<script>
varws = newWebSocket('ws://localhost:80');
ws.onopen = function() {
console.log('ws onopen');
ws.send('from client: hello');
};
ws.onmessage = function(e) {
console.log('ws onmessage');
console.log('from server: '+ e.data);
};
...
</script>
更详细的资料,请阅读:《WebSocket详解(三):深刻WebSocket通讯协议细节》。
WebSocket是经过事件通知的方式运行的。它包含四个事件和两个动做(发送和关闭)。
WebSocket的事件:
数据可直接经过Socket.send()方法进行传输。
经过chrome的Inspect->Network->WS,能够看到页面上的WebSocket链接。
如图Opcode为2,代表它是一个二进制帧:
WebSocket有相似tcp协议的帧格式,在此不作过多解释。(能够详细阅读:《理论联系实际:从零理解WebSocket的通讯原理、协议格式、安全性》)
参考:https://tools.ietf.org/html/rfc6455#section-5.1。
nginx官网已经给出了例子。主要是Upgrade和Connection头的设置。
Nginx的中的配置以下:
map $http_upgrade $connection_upgrade {
default upgrade;
''close;
}
location /chat/{
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
须要注意的是,nginx作负载均衡,不须要配置ip_hash等参数,nginx自然支持。因为ip_hash仅使用ip地址的前三个数字作hash,还有可能形成服务端的不均衡。
特别注意:
在IM聊天系统场景下,Nginx提供给WebSocket的这种所谓的“负载均衡”,只能解决传统分布系统中的SLB服务器要作的事。
通俗地说,Nginx只能帮助完成引导WebSocket客户链接到哪个WebSocket服务端实例,在IM集群状况下,若是两个用户处于不一样的WebSocket实例下时,它们之间的跨实例通讯,Nginx是没有办法实现的,这一块的逻辑仍是得IM开发者自已来实现。
总而言之,Nginx提供给WebSocket的所谓“负载均衡”,并非IM开发者认为的那种全功能集群!
可使用javax.WebSocket下的包,简单的实现ws服务端。目前基本能够经过注解的方式去编写代码,好比ServerEndpoint。
推荐使用基于netty的netty-socketio进行服务端的编写。因为使用的是netty,因此可以在多个层面进行切入,获取一些统计数据,执行一些控制指令。socketio是一套解决方案,它有多个语言的客户端,并处理了市面上大多数的兼容问题。
友情忠告:socket.io几乎是市面上最好的开源WebSocket解决方案,但netty-socketio这个开源工程并不是socket.io官方团队维护,而对于socket.io这个版本帝来讲,其余的非官方版本能不能即时跟进,也是一个须要考虑的风险因素。
1)通知功能:
保持一个长链接,当服务端游新的消息,可以实时的推送到使用方。像知乎的点赞通知、评论等,均可以使用WebSocket通讯。
某些使用H5的客户端,为了简化开发,也会使用WebSocket进行消息的通知,因为它是实时推送的,会有更好的用户体验。
2)数据收集:
一些次优级别的数据,好比行为日志、trace、异常执栈收集等,均可以开辟专门的WebSocket通道进行传输。这可以增长信息的集中度,并能及时的针对用户的行为进行合适的配置推送。因为大多数浏览器内核都支持,它将使客户端APM编程模型变得简单。
3)加密 && 认证:
虽然使用Fiddler、Charles等可以抓到不少WebSocket包。但若是同时开启SSL,传输加密后的二进制数据,会大幅增长破解的成本,会安全的多。
4)反向控制钩子:
这个...因为是双工长链接,服务端彻底能够推送一些钩子命令,甚至直接是代码,在客户端进行执行。好比截个屏,录个音,种个小马。用户只要经过了受权申请,剩下的就随你发挥了。
支付宝偷偷调用你的相机给你拍照的梗,我是相信的。
想当年,cometd的出现,惊为天人,振奋了好久。但技术突飞猛进,cometd已经衰老,而Socket.io获得了快速发展。WebSocket通过一段时间的混沌期,规范已经愈来愈完善,使用也愈来愈方便,不须要再处理那么多的兼容。
但它的本质,仍是新瓶装旧酒,换汤不换药。WebSocket的发展得益于HTML5规范的制定。规范的意义,就是约束厂商们天马行空的实现,以及指明发展的方向。
这固然有典型的反例,那就是ie。如今,只有一群公认的**,还坚持在用。
《新手入门贴:史上最全Web端即时通信技术原理详解》
《Web端即时通信技术盘点:短轮询、Comet、Websocket、SSE》
《SSE技术详解:一种全新的HTML5服务器推送事件技术》
《Comet技术详解:基于HTTP长链接的Web端实时通讯技术》
《新手快速入门:WebSocket简明教程》
《WebSocket详解(一):初步认识WebSocket技术》
《WebSocket详解(二):技术原理、代码演示和应用案例》
《WebSocket详解(三):深刻WebSocket通讯协议细节》
《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》
《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》
《WebSocket详解(六):刨根问底WebSocket与Socket的关系》
《socket.io实现消息推送的一点实践及思路》
《LinkedIn的Web端即时通信实践:实现单机几十万条长链接》
《Web端即时通信技术的发展与WebSocket、Socket.io的技术实践》
《Web端即时通信安全:跨站点WebSocket劫持漏洞详解(含示例代码)》
《开源框架Pomelo实践:搭建Web端高性能分布式IM聊天服务器》
《使用WebSocket和SSE技术实现Web端消息推送》
《详解Web端通讯方式的演进:从Ajax、JSONP 到 SSE、Websocket》
《MobileIMSDK-Web的网络层框架为什么使用的是Socket.io而不是Netty?》
《理论联系实际:从零理解WebSocket的通讯原理、协议格式、安全性》
《微信小程序中如何使用WebSocket实现长链接(含完整源码)》
《八问WebSocket协议:为你快速解答WebSocket热门疑问》
>> 更多同类文章 ……
(本文同步发布于:http://www.52im.net/thread-2488-1-1.html)