注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

itoedr的it学苑

记录从IT文盲学到专家的历程

 
 
 

日志

 
 

Web Sockets:认识html5之websocket协议  

2014-10-10 17:50:04|  分类: web app开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

什么是Web Sockets?

websoscket的通讯过程
Websocket协议随html5标准发布。它解决了HTTP中长连接通讯的这几个难题。
        被动性,当服务端服务器接受到客户端websoscket请求后,完成协议升级后(HTTP->Websocket),服务端就可以主动推送信息给客户端啦,不需要客户端再不断发出联接请求。
        其操作过程可模拟如下:
客户端请求:hello,我要建立Websocket协议,需要的服务:chat,Websocket协议版本:17(HTTP Request)
服务端回答:ok,确认(马上开始支持websoscke通讯协议),并回应“已升级为Websocket协议(HTTP Protocols Switched)”
客户端请求:麻烦你有信息的时候推送给我吧。
服务端回应:ok,有的时候会告诉你的。
服务端工作:记录下客户端状态,随时将对就主动推送。
         因此websocket,常联接通讯就成了这种结果:只需要经过一次客户端HTTP请求,就可以连续得到服务侧的源源不断的主动信息传送了。
          这个结果可以理解为程序设计中的回调:你有信息了再来通知我,而不需要客户端每次跑去向服务器请示。
          这样的websocket通讯协议解决了以前http协议的同步延迟,而且在客户端与服务器侧同时耗损资源的问题。
那么为什么websocket会解决服务器上消耗资源的问题呢?
           假如我们使用的是nginx来做服务器,其实我们所用的程序是要经过两层代理的,即HTTP协议在Nginx等服务器的解析下,然后再传送给相应的Handler(PHP等)来处理。
           借用一位朋友解说:简单地说,我们有一个非常快速的接线员(Nginx),他负责把问题转交给相应的客服(Handler)
         本身接线员基本上速度是足够的,但是每次都卡在客服(Handler)了,老有客服处理速度太慢,导致客服不够。
          Websocket就解决了这样一个难题,建立后,可以直接跟接线员建立持久连接,有信息的时候客服想办法通知接线员,然后接线员在统一转交给客户。
            这样就可以解决客服处理速度过慢的问题了。
             同时,在传统的方式上,要不断的建立,关闭HTTP协议,由于HTTP是非状态性的,每次都要重新传输identity info(鉴别信息),来告诉服务端你是谁。
            虽然接线员很快速,但是每次都要听这么一堆,效率也会有所下降的,同时还得不断把这些信息转交给客服,不但浪费客服的处理时间,而且还会在网路传输中消耗过多的流量/时间。
           但是Websocket只需要一次HTTP握手,所以说整个通讯过程是建立在一次连接/状态中,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请求,这样就解决了接线员要反复解析HTTP协议,还要查看identity info的信息。
          同时由客户主动询问,转换为服务器(推送)有信息的时候就发送(当然客户端还是等主动发送信息过来的),没有信息的时候就交给接线员(Nginx),不需要占用本身速度就慢的客服(Handler)

Web Sockets是在一个(TCP)接口进行双向通信的技术,PUSH技术类型。同时Web Sockets仍将基于W3C标准。

Web Sockets将会替代什么?

Web Sockets可以替代Long Polling(PHP服务端推送技术),这是一个有趣的概念。客户端发送一个请求到服务器,现在,服务器端并不会响应还没准备好的数据,它会保持连接的 打开状态直到最新的数据准备就绪发送,之后客户端收到数据,然后发送另一个请求。

这有它的好处:减少任一连接的延迟,当一个连接已经打开时就不需要创建另一个新的连接。但是Long-Polling并不是什么花俏技术,他仍有可能发生请求暂停,因此会需要建立新的连接。

一些Ajax应用使用上述技术-这经常是归因于低资源利用。试想一下,如果服务器在早晨会自启动并发送数据到那些希望接收而不用提前建立一些连接端口的客户端,这是一件多棒的事情啊!

       下面的例子一位作者使用php技术的websocket实现。作者详细描述关于客户端的创建而不是服务器端的执行等操作。

第一步:搞定Web Socket服务器

        启动Apache服务器:这对于linux系统用户与windows用户都很简单。

第二步:修改URLs和端口  

       根据你之前的安装修改服务器,下面是setup.class.php中的例子(服务器侧的内容):

  1. public function __construct($host='localhost',$port=8000,$max=100)    
  2.    $this->createSocket($host,$port);    

       浏览文件并在适当情况下进行更改。

第三步:开始创建客户端  

     下面来创建基本模板,这是client.php文件:

    <!DOCTYPE html>    
    <html>    
    <head>    
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>    
    <title>Web Sockets Client</title>   
    </head>   
    <body>   
    <div id="wrapper">   
               <div id="container">   
                    <h1>Web Sockets Client</h1>   
                             <div id="chatLog">   
                            </div><!-- #chatLog -->   
                   <p id="examples">e.g. try 'hi', 'name', 'age', 'today'</p>   
                             <input id="text" type="text" />   
                             <button id="disconnect">Disconnect</button>   
           </div><!-- #container -->   
</div>   
</body>   
</html>?  

            这里创建了基本模板:1)一个chat log容器,2)一个input输入框和3)一个断开连接的按钮。

第四步:添加一些CSS(提高可视性)  

         body { font-family:Arial, Helvetica, sans-serif; }    

  1. #container{ border:5px solid grey; width:800px;    margin:0 auto;    padding:10px;    }    
  2. #chatLog{  padding:5px;    border:1px solid black;    }    
  3. #chatLog p {    margin:0;    }    
  4. .event {    color:#999;    }    
  5. .warning{     font-weight:bold;    color:#CCC;    }  

第五步:Web Socket事件

        首先让我们尝试并理解Web Socket事件的概念:

2014年10月10日 - itoedr - itoedr的it学苑
 

◆onopen: 当接口打开时

◆onmessage: 当收到信息时

◆onclose: 当接口关闭时

         我们如何来实现呢?首先创建Web Socket对象。

  1. var socket = new Web Socket("ws://localhost:8000/socket/server/startDaemon.php"); 

然后向下面这样检测事件:

  1.  socket.onopen = function(){     alert("Socket has been opened!");    }  

当我们收到信息时这样做:

  1.  socket.onmessage = function(msg){     alert(msg); //Awesome!    }  

但我们还是尽量避免使用alert,现在我们可以把我们学的东西整合到客户端页面中了。


第六步:JavaScript

          首先我们将代码放到jQuery 的 document.ready函数中,然后我们还要检查用户的浏览器是否支持Web Socket。如果不支持,我们就添加一个链向Chrome浏览器页面的链接。

  1.  $(document).ready(function() {    
  2.     if(!("Web Socket" in window)){    
  3.         $('#chatLog, input, button, #examples').fadeOut("fast");    
  4.         $('<p>Oh no, you need a browser that supports Web Sockets. How about <a href="http://www.google.com/chrome">Google Chrome</a>?</p>').appendTo('#container');    
  5.     }else{    
  6.     
  7.     //The user has Web Sockets    
  8.     
  9.     connect();    
  10.     
  11.     function connect(){    
  12.         //the connect function code is below    
  13.     
  14.     }    
  15. });  

        如你所见,如果用户浏览器支持Web Socket,我们将执行connect()函数。这里是核心功能,我们将开始创建open、close和receive事件。我们将在我们的服务器定义URL。

  1. var socket;    
  2. var host = "ws://localhost:8000/socket/server/startDaemon.php";  

你可能会发现URL中怎么没有http?恩,是的,这是一个Web Socket URL,使用了不同的协议。下面是URL分解图示:

2014年10月10日 - itoedr - itoedr的it学苑
 

        下面让我们继续完成connect()函数,我们将代码放入try/catch块,这样如果代码出现问题,我们能让用户知道。我们创建Web Socket,并将信息传递到message()函数,之后会做讲解。我们创建我们的onopen、onmessage和onclose函数. 需要注意的是我们为用户提供了端口状态,这并不是必需的,但我们把它放进来主要是为了方便调试。

  1. CONNECTING = 0 
  2. OPEN = 1 
  3. CLOSED = 2 
  4.  
  5.  function connect(){    
  6.     try{    
  7.     
  8.     var socket;    
  9.     var host = "ws://localhost:8000/socket/server/startDaemon.php";    
  10.     var socket = new Web Socket(host);    
  11.     
  12.         message('<p class="event">Socket Status: '+socket.readyState);    
  13.     
  14.         socket.onopen = function(){    
  15.              message('<p class="event">Socket Status: '+socket.readyState+' (open)');    
  16.         }    
  17.     
  18.         socket.onmessage = function(msg){    
  19.              message('<p class="message">Received: '+msg.data);    
  20.         }    
  21.     
  22.         socket.onclose = function(){    
  23.              message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');    
  24.         }               
  25.     
  26.     } catch(exception){    
  27.          message('<p>Error'+exception);    
  28.     }    
  29. }   

message()函数很简单, 它将我们想展现给用户的文本填入chat log容器内。 我们在socket事件函数中为段落(<p>)标签创建适当的class,我们在message函数中只有一个段落结束标签。

  1.  function message(msg){    
  2.     $('#chatLog').append(msg+'</p>');    
  3. }  

目前的成果

如果你已按上面教程按部就班的做的话,很好,我们已经创建了HTML/CSS模板、创建并建立Web Socket连接、通过创建连接保持用户的进展更新。

2014年10月10日 - itoedr - itoedr的it学苑
 

第七步:发送数据

         现在我们已经有了提交按钮,但我们还需要监听用户按下键盘的事件,并运行send函数,下面的’13′便是回车键对应的ASCII码。

  1.  $('#text').keypress(function(event) {    
  2.     if (event.keyCode == '13') {    
  3.         send();    
  4.     }    
  5. });  

下面是send()函数:

  1. function send(){    
  2.    
  3.    var text = $('#text').val();    
  4.    if(text==""){    
  5.        message('<p class="warning">Please enter a message');    
  6.        return ;    
  7.    }    
  8.    try{    
  9.        socket.send(text);    
  10.        message('<p class="event">Sent: '+text)    
  11.    } catch(exception){    
  12.    message('<p class="warning"> Error:' + exception);    
  13.    }    
  14.    
  15.    $('#text').val("");    
  16.    
  17.   

下面我们需要:

  1. socket.send();

那些额外的代码做了以下工作:检测用户是否什么都没输入却仍点击返回、清空input输入框、执行message()函数。


第八步:关闭Socket
关闭Socket操作相当简单,添加对断开连接按钮的click事件监听就可以。

2014年10月10日 - itoedr - itoedr的it学苑
         $('#disconnect').click(function(){ socket.close();  }); 

完整JavaScript代码

  1.  $(document).ready(function() {    
  2.     
  3.   if(!("Web Socket" in window)){    
  4.   $('#chatLog, input, button, #examples').fadeOut("fast");    
  5.   $('<p>Oh no, you need a browser that supports Web Sockets. How about <a href="http://www.google.com/chrome">Google Chrome</a>?</p>').appendTo('#container');    
  6.   }else{    
  7.       //The user has Web Sockets    
  8.     
  9.       connect();    
  10.     
  11.       function connect(){    
  12.           var socket;    
  13.           var host = "ws://localhost:8000/socket/server/startDaemon.php";    
  14.     
  15.           try{    
  16.               var socket = new Web Socket(host);    
  17.     
  18.               message('<p class="event">Socket Status: '+socket.readyState);    
  19.     
  20.               socket.onopen = function(){    
  21.                  message('<p class="event">Socket Status: '+socket.readyState+' (open)');    
  22.               }    
  23.     
  24.               socket.onmessage = function(msg){    
  25.                  message('<p class="message">Received: '+msg.data);    
  26.               }    
  27.     
  28.               socket.onclose = function(){    
  29.                 message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');    
  30.               }             
  31.     
  32.           } catch(exception){    
  33.              message('<p>Error'+exception);    
  34.           }    
  35.     
  36.           function send(){    
  37.               var text = $('#text').val();    
  38.     
  39.               if(text==""){    
  40.                   message('<p class="warning">Please enter a message');    
  41.                   return ;    
  42.               }    
  43.               try{    
  44.                   socket.send(text);    
  45.                   message('<p class="event">Sent: '+text)    
  46.     
  47.               } catch(exception){    
  48.                  message('<p class="warning">');    
  49.               }    
  50.               $('#text').val("");    
  51.           }    
  52.     
  53.           function message(msg){    
  54.             $('#chatLog').append(msg+'</p>');    
  55.           }    
  56.     
  57.           $('#text').keypress(function(event) {    
  58.               if (event.keyCode == '13') {    
  59.                 send();    
  60.               }    
  61.           });       
  62.     
  63.           $('#disconnect').click(function(){    
  64.              socket.close();    
  65.           });    
  66.     
  67.       }//End connect    
  68.     
  69.   }//End else    
  70.     
  71. });  

第九步:运行Web Socket服务器

我们要输入一些命令行,XAMPP提供了比较方便的shell选项。点击XAMPP控制面板的’shell’按钮并输入:

2014年10月10日 - itoedr - itoedr的it学苑
 
  1. php -q path\to\server.php

现在你已经运行了Web Socket服务器!

功成!

2014年10月10日 - itoedr - itoedr的it学苑
 

HTML 5 Web Socket的最新动态:The Web Socket API

  评论这张
 
阅读(174)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017