资讯专栏INFORMATION COLUMN

Websocket解析及实现

XboxYan / 3612人阅读

摘要:早期的轮询是通过不断自动刷新页面而实现的。长轮询的另一个问题是缺乏标准实现。服务器端接到这个请求后作出回应并不断更新连接状态以保证客户端和服务器端的连接不过期。协议解析协议包含两部分一部分是握手,一部分是数据传输。

Websocket是什么?

Websocket是一个因为应用场景越来越复杂而提出的,针对浏览器和web服务器之间双向持续通信而设计,而且优雅地兼容HTTP的协议(我猜想:同时因为建立在HTTP上,也可以利用好HTTP原有的基础比如basic认证)。

网络模型结构上来说呢,

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


与http协议的关系:

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

Websocket的作用和优点? 非WebSocket的实时信息传递技术?

WebSocket 是什么原理?为什么可以实现持久连接? - 知乎

轮询

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

ajax轮询

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

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

长轮询

长轮询(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:phpStudyWWWMonth10websocketwebsocket.php:87
Stack trace:
#0 E:phpStudyWWWMonth10websocketwebsocket.php(19): Sock->WebSocket("127.0.0.1", 8000)
#1 E:phpStudyWWWMonth10websocketwebsocket.php(5): Sock->__construct("127.0.0.1", 8000)
#2 {main}
  thrown in E:phpStudyWWWMonth10websocketwebsocket.php on line 87

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

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

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

找到php.ini,看 extension=php_gd2.dll 和 extension=php_sockets.dll 扩展是否打开;

看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原理

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/23218.html

相关文章

  • websocket历史使用详解

    摘要:握手客户端向服务端发起连接请求如图,我们在请求服务器的时候,发送了这样的。如图下面解释下字段的含义协议升级成功服务端处理之后的协议版本号协议升级为至此,握手成功下面就尽情的传输数据吧数据传输数据传输需要客户端,没什么好说的了。 一、阅前热身 什么是keep-alive 1、keep-alive只是客户端的一种建议 我们打开百度首页,进一步查看header。 showImg(https:...

    duan199226 评论0 收藏0
  • 细说WebSocket - Node篇

    摘要:一协议概述协议允许不受信用的客户端代码在可控的网络环境中控制远程主机。该协议包含一个握手和一个基本消息分帧分层通过。该协议包括两个方面,握手链接和数据传输。二注意事项很多人可能只是到,但事实上协议地址是可以加和的。 本文同步自我的博客园:http://hustskyking.cnblogs.com P.S:文章代码格式错乱,也不知道是什么原因,还望@segmentFault的兄弟看下~...

    wapeyang 评论0 收藏0
  • JSONP CORS WebSocket

    摘要:下表给出了相对于同源检测的结果跨域解决方法由两部分组成回调函数和数据。回调函数时当响应到来是应该在页面中调用的函数,名字一般在请求中指定。 何为跨域? 一般情况下,XMLHttpRequest(XHR)对象只能访问与包含它的页面位于同一个域中的资源,这种安全策略可以预防某些恶意行为,即通常所说的同源策略。 只要协议、域名、端口号有任何一个不同,都会被当成不同的域。 下表给出了相对于 h...

    honhon 评论0 收藏0
  • WEB前端面试题汇总(JS)

    摘要:如何解决跨域问题跨域原因由于浏览器的同源策略限制,只允许请求当前源域名协议端口的资源。同源策略同源策略是客户端脚本尤其是的重要的安全度量标准。同源策略指的是协议,域名,端口相同,同源策略是一种安全协议。状态表示客户端已发送报文。 如何解决跨域问题: 跨域原因:由于浏览器的同源策略限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。在脚本中发起HTTP请求,出于...

    meislzhua 评论0 收藏0

发表评论

0条评论

XboxYan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<