Websocket解析及实现

Websocket是什么?

Websocket是一个由于应用场景愈来愈复杂而提出的,针对浏览器和web服务器之间双向持续通讯而设计,并且优雅地兼容HTTP的协议(我猜测:同时由于创建在HTTP上,也能够利用好HTTP原有的基础好比basic认证)。php

网络模型结构上来讲呢,html

WebSocket 实际上指的是一种协议,与咱们熟知的Http协议是同等的一个网络协议。用网络模型结构来解释的话,WebSocket和Http协议都属于应用层协议,二者都基于传输层的TCP协议。
websocket协议本质上是一个基于tcp的协议,是先经过HTTP/HTTPS协议发起一条特殊的http请求进行握手后建立一个用于交换数据的TCP链接,此后服务端与客户端经过此TCP链接进行实时通讯。html5


与http协议的关系:jquery

WebSocket不是Http协议,Http协议只是被WebSocket使用来创建链接,链接创建了之后客户端与服务器的双向通讯就与Http无关了。
借用了http的协议完成握手的一个新协议,能够说是基于http协议,能够说是http协议的一种补充,也能够说与http协议毫无关系nginx

Websocket的做用和优势?

非WebSocket的实时信息传递技术?

WebSocket 是什么原理?为何能够实现持久链接? - 知乎git

  • 轮询

轮询是由客户端定时向服务端发起查询数据的请求的一种实现方式。早期的轮询是经过不断自动刷新页面而实现的。
在特定的时间间隔(例如1秒),由浏览器向服务器发出一个Http Request,而后服务器返回最新的数据给客户端浏览器,从而给出一种服务端实时推送的假象。因为Http Request的Header(请求头)很长,而传输的数据可能很短就只占一点点,每次请求消耗的带宽和服务器资源大部分都消耗在Header上。(想一想ajax技术和全页面传值的资源消耗)github

  • ajax轮询

ajax轮询,又被称为Comet,由客户端不停地请求服务器端,查询有没有新消息,而后再由服务器返回结果;是轮询的一种优化,实现了无刷新更新数据,而且不用传递header头的信息,传递内容更少。web

但本质上这些方式均是客户端定时轮询服务端,这种方式的最显著的缺点是若是客户端数量庞大而且定时轮询间隔较短服务端将承受响应这些客户端海量请求的巨大的压力。ajax

  • 长轮询

长轮询(long polling)是另外一种流行的通讯方法,客户端向服务器请求信息,并在设定的时间段内打开一个链接。服务器若是没有任何信息,会保持请求打开,直到有客户端可用的信息,或者直到指定的超时时间用完为止。这时,客户端从新向服务器请求信息。长轮询也称做Comet(前面已经提到过)或者反向AJAX。Comet延长HTTP响应的完成,直到服务器有须要发送给客户端的内容,这种技术经常称做“挂起GET”或“搁置POST”。重要的是要知道,当信息量很大时,长轮询相对于传统轮询并无明显的性能优点,由于客户端必须频繁地重连到服务器以读取新信息,形成网络的表现和快速轮询相同。长轮询的另外一个问题是缺少标准实现。算法

长轮询其实原理跟ajax轮询差很少,都是采用轮询的方式,不过采起的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,经过一次请求,询问服务器有没有新消息更新,若是没有新消息时,会保持长链接,就一直不返回Response给客户端。直到有消息才返回,返回完以后,客户端再次创建链接,周而复始。

在数据更新不够频繁的状况下,使用轮询方法获取数据时客户端常常会获得没有数据的响应,显然这样的轮询是一个浪费网络资源的无效的轮询。长轮询则是针对普通轮询的这种缺陷的一种改进方案,其具体实现方式是若是当前请求没有数据能够返回,则继续保持当前请求的网络链接状态,直到服务端有数据能够返回或者链接超时。长轮询经过这种方式减小了客户端与服务端交互的次数,避免了一些无谓的网络链接。可是若是数据变动较为频繁,则长轮询方式与普通轮询在性能上并没有显著差别。同时,增长链接的等待时间,每每意味着并发性能的降低。

长轮询虽然下降了服务器的负载,可是须要服务器有很高的并发能力才能够。
而目前处理高并发的模型基本都是异步非阻塞的模型(好比nginx)。
既想阻塞,又想高并发,几乎不可能。

所谓流是指客户端在页面之下向服务端发起一个长链接请求,服务端收到这个请求后响应它并不断更新链接状态,以确保这个链接在客户端与服务端之间一直有效。服务端能够经过这个链接将数据主动推送到客户端。显然,这种方案实现起来相对比较麻烦,并且可能被防火墙阻断。

在流化技术中,客户端发送一个请求,服务器发送并维护一个持续更新和保持打开(能够是无限或者规定的时间段)的开放响应。每当服务器有须要交付给客户端的信息时,它就更新响应。看起来,流化是可以适应不可预测的信息交付的极佳方案,可是服务器从不发出完成HTTP响应的请求,从而使链接一直保持打开。在这种状况下,代理和防火墙可能缓存响应,致使信息交付的延迟增长。所以,许多流化的尝试对于存在防火墙和代理的网络是不友好的。

流技术方案一般就是在客户端的页面使用一个隐藏的窗口向服务端发出一个长链接的请求。服务器端接到这个请求后做出回应并不断更新链接状态以保证客户端和服务器端的链接不过时。经过这种机制能够将服务器端的信息源源不断地推向客户端。这种机制在用户体验上有一点问题,须要针对不一样的浏览器设计不一样的方案来改进用户体验,同时这种机制在并发比较大的状况下,对服务器端的资源是一个极大的考验。

传统方法的缺点?

Web 通讯 之 长链接、长轮询(long polling) - hoojo - 博客园

上述方法提供了近乎实时的通讯,
可是它们也涉及HTTP请求和响应首标,
包含了许多附加和没必要要的首标数据与延迟。

此外,在每一种状况下,客户端都必须等待请求返回,才能发出后续的请求,而这显著地增长了延迟。

以上四种方法的后三种呢,都实现了真正的双工通讯,但都是单向连接,须要被动的请求服务器,而不是由服务器自动发给客户端。(仍是在代码层面上下功夫,可是这种状况下,明显须要从协议层去想办法)

首先就是很是消耗资源,不断地创建HTTP链接,而后等待服务端处理,能够体现HTTP协议的另一个特色,被动性。其次呢,
ajax轮询须要服务器有很快的处理速度和资源,
长轮询须要有很高的并发,也就是同时处理请求的能力

Websocket的优势?

基于此,websocket出现了,它解决了http不利于这种场景下(聊天,视频...)的两个问题:
http协议是一个无状态的,被动的协议(不持久,服务端没法主动发送信息给客户端)

Websocket只须要一次HTTP握手,因此说整个通信过程是创建在一次链接/状态中,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请求,这样就解决了接线员要反复解析HTTP协议,还要查看identity info的信息。

同时由客户主动询问,转换为服务器(推送)有信息的时候就发送(固然客户端仍是等主动发送信息过来的。。),没有信息的时候就交给接线员(Nginx),不须要占用自己速度就慢的客服(Handler)了

因此,,,
Websocket能更好的实现双向通讯且节省服务器资源和带宽。

websocket协议解析?

wensocket协议包含两部分:一部分是“握手”,一部分是“数据传输”。为了便于演示,咱们采用swoole创建一个websocket服务器来演示。

握手部分:

Websocket协议之握手链接 - Oshyn —— 乐而学,学而乐 - CSDN博客

①客户端向服务端发起链接请求
图片描述
如图,咱们在请求服务器的时候,发送了这样的request header。
下面咱们就一些比较重要的字段信息进行说明:

* Connection:Upgrade #通知服务器协议升级 Upgrade:websocket  #协议升级为websocket协议
* Host:0.0.0.0:9501  #升级协议的服务主机:端口地址
* Sec-WebSocket-Key:K8o1cNIxO2pR6inTIDBSgg== #传输给服务器的key
* Sec-WebSocket-Version:13 #websocket协议版本13

Sec-WebSocket-Key有什么用呢?客户端将这个key发送给服务器,服务器将这个key进行处理,将处理后的key返回给客户端,客户端根据这个key是否正确来判断是否创建链接。
②:服务端返回握手应答
图片描述
如图,咱们看到websocket协议状态码是101.

101表示协议切换成功。

咱们查看websocket的response header。如图:
图片描述
下面解释下reponse header字段的含义

* Connection:Upgrade #协议升级成功
* Sec-WebSocket-Accept:GnoYH/ip/ZMh+a5rX5P/YR6e68g= #服务端处理以后的key
* Sec-WebSocket-Version:13#websocket 协议版本号
* Upgrade:websocket#协议升级为websocket

至此,websocket握手成功!下面就尽情的传输数据吧!

数据传输部分:

数据传输须要客户端,非websocket客户端不能与websocket服务器通讯,那么怎么实现websocket客户端呢?

* Chrome/Firefox/高版本IE/Safari等浏览器内置了JS语言的WebSocket客户端

* 可使用一些扩展来实现websocket客户端。如php的swoole、workerman。

怎么使用websocket实现聊天室?

能够参考的DEMO

PHP源码及DEMO:
洞悉/websocket - 码云

swoole 服务端120行代码构建一个websocket 聊天室. - 我的文章 - SegmentFault

基于swoole和websocket的直播摄像头的demo

NodeJS实现Websocket聊天室:
利用express+socket.io实现一个简易版聊天室 - zp的笔记 - SegmentFault

JAVA实现websocket聊天室:
websocket笔记以及一个微型聊天室例子 - niiiu的web杂谈 - SegmentFault

可能出现的问题?

Chrome下会报这个

WebSocket connection to 'ws://127.0.0.1:8000/' failed: Error in
connection establishment: net::ERR_CONNECTION_REFUSED

Firefox下会报这个

Firefox 没法创建到 ws://... 服务器的链接;

那么如何解决呢?
目前来看,主要是三个方面的问题,

* URL路径,这个要注意一下文件名或者路径是否是有问题; 
* 其次,看下浏览器的支持问题,是否有须要开启的配置;
* 最后,看看是否是websocket的进程是否是不在运行中,不然浏览器会链接不上;

第二种问题很容易解决了,about:config里搜websocket,检查是否有错误的配置项。

这里着重说下最后一种问题,

运行程序以前,要先在服务器跑一下他的php文件
在命令行cd到文件夹下php websocket.php,报的这个错

PHP Fatal error:  Uncaught Error: Call to undefined function socket_create() in E:\phpStudy\WWW\Month10\websocket\websocket.php:87
Stack trace:
#0 E:\phpStudy\WWW\Month10\websocket\websocket.php(19): Sock->WebSocket('127.0.0.1', 8000)
#1 E:\phpStudy\WWW\Month10\websocket\websocket.php(5): Sock->__construct('127.0.0.1', 8000)
#2 {main}
  thrown in E:\phpStudy\WWW\Month10\websocket\websocket.php on line 87

Fatal error: Uncaught Error: Call to undefined function socket_create() in E:\phpStudy\WWW\Month10\websocket\websocket.php:87
Stack trace:
#0 E:\phpStudy\WWW\Month10\websocket\websocket.php(19): Sock->WebSocket('127.0.0.1', 8000)
#1 E:\phpStudy\WWW\Month10\websocket\websocket.php(5): Sock->__construct('127.0.0.1', 8000)
#2 {main}
  thrown in E:\phpStudy\WWW\Month10\websocket\websocket.php on line 87

注意要开启websocket的php拓展,解决方法以下:

遭遇了"Call to undefined function socket_create()" - 可视化空间 - ITeye博客

  1. 找到php.ini,看 extension=php_gd2.dll 和 extension=php_sockets.dll 扩展是否打开;
  2. 看phpInfo()显示的内容里,socket模块是否为enable;

我检查了一下,发现都是符合的。但错误仍然出现?怎么回事呢?

后来我才发现,原来是我在phpInfo()里看到的和在cmd窗口里使用的php不是同一个东西。

缘由是我屡次安装过php. 先前的php在系统的环境变量里面注册了path。因此在cmd窗口里使用的是之前的php.
而在phpInfo()里显示的是如今的php的设置。

解决的办法很简单了,就把系统环境变量里的path里,指向老的Php的路径改成指向正在使用的Php的路径。这样在cmd里的php和在浏览器里的php就是同一个东西了。

Websocket的应用场景?

决定手头的工做是否须要使用WebSocket技术的方法很简单:

* 你的应用提供多个用户相互交流吗?
* 你的应用是展现服务器端常常变更的数据吗?

若是你的回答是确定的,那么请考虑使用WebSocket。若是你仍然不肯定,并想要更多的灵感,这有一些杀手锏的案例。

1.社交订阅
对社交类的应用的一个裨益之处就是可以即时的知道你的朋友正在作什么。虽然听起来有点可怕,可是咱们都喜欢这样作。你不会想要在数分钟以后才能知道一个家庭成员在馅饼制做大赛获胜或者一个朋友订婚的消息。你是在线的,因此你的订阅的更新应该是实时的。
2.多玩家游戏
网络正在迅速转变为游戏平台。在不使用插件(我指的是Flash)的状况下,网络开发者如今能够在浏览器中实现和体验高性能的游戏。不管你是在处理DOM元素、CSS动画,HTML5的canvas或者尝试使用WebGL,玩家之间的互动效率是相当重要的。我不想在我扣动扳机以后,个人对手却已经移动位置。

3.协同编辑/编程
咱们生活在分布式开发团队的时代。平时使用一个文档的副本就知足工做需求了,可是你最终须要有一个方式来合并全部的编辑副本。版本控制系统,好比Git可以帮助处理某些文件,可是当git发现一个它不能解决的冲突时,你仍然须要去跟踪人们的修改历史。经过一个协同解决方案,好比WebSocket,咱们可以工做在同一个文档,从而省去全部的合并版本。这样会很容易看出谁在编辑什么或者你在和谁同时在修改文档的同一部分。
4.点击流数据
分析用户与你网站的互动是提高你的网站的关键。HTTP的开销让咱们只能优先考虑和收集最重要的数据部分。而后,通过六个月的线下分析,咱们意识到咱们应该收集一个不一样的判断标准——一个看起来不是那么重要可是如今却影响了一个关键的决定。与HTTP请求的开销方式相比,使用Websocket,你能够由客户端发送不受限制的数据。想要在除页面加载以外跟踪鼠标的移动?只须要经过WebSocket链接发送这些数据到服务器,并存储在你喜欢的NoSQL数据库中就能够了(MongoDB是适合记录这样的事件的)。如今你能够经过回放用户在页面的动做来清楚的知道发生了什么。

5.股票基金报价
金融界瞬息万变——几乎是每毫秒都在变化。咱们人类的大脑不能持续以那样的速度处理那么多的数据,因此咱们写了一些算法来帮咱们处理这些事情。虽然你不必定是在处理高频的交易,可是,过期的信息也只能致使损失。当你有一个显示盘来跟踪你感兴趣的公司时,你确定想要随时知道他们的价值,而不是10秒前的数据。使用WebSocket能够流式更新这些数据变化而不须要等待。
6.体育实况更新
如今咱们开始讨论一个让人们激情澎湃的愚蠢的东西——体育。我不是运动爱好者,可是我知道运动迷们想要什么。当爱国者在打比赛的时候,个人妹夫将会沉浸于这场比赛中而不能自拔。那是一种疯狂痴迷的状态,彻底发自心里的。我虽然不理解这个,可是我敬佩他们与运动之间的这种强烈的联系,因此,最后我能作的就是给他的体验中下降延迟。若是你在你的网站应用中包含了体育新闻,WebSocket可以助力你的用户得到实时的更新。

7.多媒体聊天视频会议并不能代替和真人相见,但当你不能在同一个屋子里见到你谈话的对象时,视频会议是个不错的选择。尽管视频会议私有化作的“不错”,但其使用仍是很繁琐。我但是开放式网络的粉丝,因此用WebSockets getUserMedia API和html5音视频元素明显是个不错的选择。WebRTC的出现瓜熟蒂落的成为我刚才归纳的组合体,它看起来颇有但愿,但其缺少目前浏览器的支持,因此就取消了它成为候选人的资格。

8.基于位置的应用
愈来愈多的开发者借用移动设备的GPS功能来实现他们基于位置的网络应用。若是你一直记录用户的位置(好比运行应用来记录运动轨迹),你能够收集到更加细致化的数据。若是你想实时的更新网络数据仪表盘(能够说是一个监视运动员的教练),HTTP协议显得有些笨拙。借用WebSocket TCP连接可让数据飞起来。
9.在线教育上学花费愈来愈贵了,但互联网变得更快和更便宜。在线教育是学习的不错方式,尤为是你能够和老师以及其余同窗一块儿交流。很天然,WebSockets是个不错的选择,能够多媒体聊天、文字聊天以及其它优点如与别人合做一块儿在公共数字黑板上画画...

其余

Websocket攻击

【技术分享】WebSocket漏洞与防御详解_黑客技术

一个socket是一次网络通讯中的一个端点。socket老是分为两部分:一个IP地址和一个端口。

例如:当您访问www.securelayer7.net时,你的计算机和网站的服务器正在使用socket(端点)进行通讯。网站的端点将是:www.securelayer7.net:80,你的计算机的端点将是你的IP地址,后跟任何随机端口号,如192.168.0.111:6574

跨站websocket劫持
网络敏感信息泄露
DDOS攻击(默认状况下,WebSockets容许无限制的链接致使DOS)

参考文档

WebSocket初探

WebSocket实现原理

WebSocket 是什么原理?如何实现消息实时推送?

WebSocket原理

相关文章
相关标签/搜索