如今,不少网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,而后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器须要不断的向服务器发出请求,然而HTTP request的header是很是长的,里面包含的数据可能只是一个很小的值,这样会占用不少的带宽和服务器资源。php
而比较新的技术去作轮询的效果是Comet,使用了AJAX。但这种技术虽然可达到双向通讯,但依然须要发出请求,并且在Comet中,广泛采用了长连接,这也会大量消耗服务器带宽和资源。jquery
用大白话揭开Ajax长轮询(long polling)的神秘面纱编程
面对这种情况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通信。json
国际惯例,先上维基百科的解释。segmentfault
"WebSocket是HTML5开始提供的一种在单个 TCP 链接上进行全双工通信的协议。"设计模式
——维基百科浏览器
上面是维基百科对WebSocket的解释,别问我如何解释上面这段话,由于我也没看懂,那么下面我用人话解释一下吧(仅仅是个人理解):服务器
WebSocket是一个协议,能够简单当作是HTTP协议的一个补充协议,WebSocket借助HTTP协议的基础完成服务器主动与客户端实时传输数据。
这是WebSocket和HTTP之间的关系,有交集,可是并非所有。
WebSocket只是HTML5其中的一个API(HTML5推出了不少新的API,赞),这个API能够经过WebSocket协议实现WebSocket技术。
在WebSocket API中,浏览器和服务器只须要作一个握手的动做,而后,浏览器和服务器之间就造成了一条快速通道。二者之间就直接能够数据互相传送。
关键点在于如何"握手",只要咱们完成了握手的这个工做,那么WebScoket技术就算是可以使用了。
前面说了WebSocket与HTTP有交集的,或者能够说WebSocket借助了HTTP的基础就是体如今这里了,能够看到图中的红点,分别是WebSocket的请求头和响应头,一来一回,握手也就完成了,实时链接也就创建起来了!
下面讲解一下几个重要的头参数:
Request: Upgrade:WebSocket; //指定WebSocket协议 Sec-WebSocket-Version: 13 //指定Websocket Draft协议版本 Sec-WebSocket-Key:Cv8RLRCr07Ujlqexqq9Nrw== //验证key值,由浏览器随机生成,能够理解为一个校验码 Reponse: Connection:Upgrade ; Upgrade:webSocket;//没错我就是webSocket Sec-WebSocket-Accept:rC+mM80welcslAqBHpav4MSDzAU= ;//这是返回头校验码,和请求头的Key配对 Sec-WebSocket-Version: 13 //指定Websocket Draft协议版本
以上就是一次完成的WebSocket握手,握手完以后就能够进行实时通讯了。
先上个代码看看:
本文所用服务端语言为PHP,其余语言能够对照着看,大的原理都同样:
WebSocket Demo下载连接(代码实在太长,直接下载吧)
使用方法
Windows下要用cmd启动server.php文件,Linux同理 而后用浏览器访问index.html Demo是上网找的,不能当作实际用途,简单看看运行流程就好
代码须要改的就是index.html的url和server.php的ip。
我讲解几个重要的模块
server.php:
<?php include 'websocket.class.php'; $config=array( 'address'=>'127.0.0.1', 'port'=>'8000', 'event'=>'WSevent',//回调函数的函数名 'log'=>true, ); $websocket = new websocket($config); $websocket->run();
server.php:经过cmd运行server.php,引用并实例化websocket.class.php类库,并执行run方法,使其充当一个"服务器",持续挂着这个链接,当客户端有消息就作出对应动做。
Index.html:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>websocket_TEST</title> <script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script> </head> <body> <textarea class="log" style="width: 100%; height: 500px;"> =======websocket====== </textarea> <input type="button" value="链接" onClick="link()"> <input type="button" value="断开" onClick="dis()"> <input type="text" id="text"> <input type="button" value="发送" onClick="send()"> <script> function link(){ var url='ws://127.0.0.1:8000'; socket=new WebSocket(url); socket.onopen=function(){log('链接成功')} socket.onmessage=function(msg){log('得到消息:'+msg.data);console.log(msg);} socket.onclose=function(){log('断开链接')} } function dis(){ socket.close(); socket=null; } function log(var1){ $('.log').append(var1+"\r\n"); } function send(){ socket.send($('#text').attr('value')); } function send2(){ var json = JSON.stringify({'type':'php','msg':$('#text2').attr('value')}) socket.send(json); } </script> </body> </html>
Index.html:HTML5提供了WebSocket API,因此,客户端实例化此API,参数为IP:端口,链接上服务端的WebSocket链接。
function roboot()
<? function roboot($sign,$t){ global $websocket; switch ($t) { case 'hello': $show='hello,GIt @ OSC'; break; case 'name': $show='Robot'; break; case 'time': $show='当前时间:'.date('Y-m-d H:i:s'); break; case '再见': $show='( ^_^ )/~~拜拜'; $websocket->write($sign,'Robot:'.$show); $websocket->close($sign); return; break; case '天王盖地虎': $array = array('小鸡炖蘑菇','宝塔震河妖','粒粒皆辛苦'); $show = $array[rand(0,2)]; break; default: $show='( ⊙o⊙?)不懂,你能够尝试说:hello,name,time,再见,天王盖地虎.'; } $websocket->write($sign,'Robot:'.$show); }
function roboot():指定了客户端的操做和服务端回复的信息,客户端发送' 天王盖地虎',服务端返回信息' 小鸡炖蘑菇'/' 宝塔震河妖'/' 粒粒皆辛苦'。
文章最后来个小科普:
关于Socket 与 WebScoket
Socket 其实并非一个协议。它工做在 OSI 模型会话层(第5层),是为了方便你们直接使用更底层协议(通常是 TCP 或 UDP )而存在的一个抽象层。
最先的一套 Socket API 是 Berkeley sockets ,采用 C 语言实现。它是 Socket 的事实标准,POSIX sockets 是基于它构建的,多种编程语言都遵循这套 API,在 JAVA、Python 中都能看到这套 API 的影子。
下面摘录一段更容易理解的文字(来自 http和socket之长链接和短链接区别):
Socket是应用层与TCP/IP协议族通讯的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来讲,一组简单的接口就是所有,让Socket去组织数据,以符合指定的协议。
主机 A 的应用程序要能和主机 B 的应用程序通讯,必须经过 Socket 创建链接,而创建 Socket 链接必须须要底层 TCP/IP 协议来创建 TCP 链接。创建 TCP 链接须要底层 IP 协议来寻址网络中的主机。咱们知道网络层使用的 IP 协议能够帮助咱们根据 IP 地址来找到目标主机,可是一台主机上可能运行着多个应用程序,如何才能与指定的应用程序通讯就要经过 TCP 或 UPD 的地址也就是端口号来指定。这样就能够经过一个 Socket 实例惟一表明一个主机上的一个应用程序的通讯链路了。
而 WebSocket 则不一样,它是一个完整的 应用层协议,包含一套标准的 API 。
因此,从使用上来讲,WebSocket 更易用,而 Socket 更灵活。
再简单来讲, Socket是一个应用程序接口,是抽象的,WebSocket和HTTP是具体实现,
参考文章:
https://www.zhihu.com/question/20215561 《 知乎回答:什么是WebSocket?》
https://zh.wikipedia.org/wiki/WebSocket 《维基百科:WebSocket》
http://zengrong.net/post/2199.htm 《zrong's blog》