转- IM设计思考:基于同步HTTP双向流(BOSH)的web im机制

http://blog.csdn.net/mindfloating/article/details/7441074

在XMPP扩展协议XEP-0124中定义了一个传输协议来模拟两个实体 (例如一个客户端和一个服务器) 之间的长连双向TCP连接的语义,它有效地运用多个同步的HTTP"请求/应答"对,而不需要使用频繁的轮询或者分块响应。该协议简称BOSH(Bidirectional-streams Over Synchronous HTTP),协议的设计目标之一是提供准TCP的连接性能同时兼容受约束的运行环境。

web im是一种具有较高实时性需求的应用,应用要求服务器能实时的将更新信息推送到浏览器客户端。而面向浏览器的消息推送技术到目前已经有了很大发展,各种技术各有优缺点和局限性,这里我们先来比较下各类“面向浏览器的服务器推”技术:

1. Flash XML Socket

该技术要求浏览器安装Flash插件,在Html页面中潜入一个使用了XML Socket类的Flash程序,通过javascript与其交互实现和服务器的长连接通信。

这项技术曾在淘宝旺旺历史上被使用过,后来因为各类兼容性问题而放弃使用。

 

2. 基于HTTP长连接的Comet

该技术要求客户端浏览器支持HTTP/1.1,HTTP/1.1协议定义的一些技术规范被应用与实践中,例如持久连接、chunked transfer-encoding、pipeline等。

对于一些受限的客户端(移动终端等)可能不能很好的支持像chunked(块传输)、pipeline等特性。

 

3. Websocket

这是HTML5的一种新协议,可能是将来实现服务器端推送的最佳方式,但不是现在。

 

4. long-polling(长轮询)

BOSH协议正是采用该方式实现,也是目前最常用的方式(兼容性和性能平衡度最好)。

因为HTTP是一个同步请求/应答协议,传统的通过HTTP模拟双向流的解决方案是让客户端HTTP间歇性地轮询服务器来查询是否有任何等待发送给客户端的数据。当没有数据需要传输的时候,这种幼稚的做法在轮询的时候浪费了很多网络带宽,它也降低了应用程序的响应,因为数据要花时间排队直到服务器从客户端接收下一次轮询 (HTTP 请求) 。 这导致了响应速度和带宽之间难免顾此失彼, 因为增加轮询频率将在减少延迟的同时增加带宽消耗 (如果轮询频率降低的话,反之亦然)。长轮询比之传统轮询的优势就在于如何实现“长”这个字上。

 

BOSH使用的技术可以描述为:

 - 客户端请求服务器后,服务器在有数据发送给客户端之前不去应答请求。服务器hold住了来自客户端的连接并等待发送给客户端的数据准备好。

 - 在服务器hold住客户端连接时,若客户端需要发送数据,假如客户端支持HTTP pipline技术则只需在该连接上再发送一个请求,若不支持,则新起一个连接发送请求。

 - BOSH要求同一个客户端不能同时建立超过2个并发连接 

 - 一旦客户端发送的第二个请求到达时,服务器立刻应答第一个请求并释放hold住的第一个请求连接,保证客户端始终能立刻发送更多数据。

 - 一段时间内连接双向都无数据传输时,服务器以空数据包应答客户端,客户端收到应答后立刻发起一个新的请求,这模拟了TCP长连接的心跳机制。

 - BOSH推送的每一个数据块都是完整的HTTP应答,不提供chunked传输。所以和Comet技术不像,BOSH能够绕过一些代理和缓冲机制,并完全兼容HTTP/1.0
 
 
下面看一下具体BOSH会话过程的示例:
 
1. BOSH会话创建请求
  1. POST /webclient HTTP/1.1  
  2. Host: httpcm.example.com  
  3. Accept-Encoding: gzip, deflate  
  4. Content-Type: text/xml; charset=utf-8  
  5. Content-Length: 104  
  6.    
  7. <body content='text/xml; charset=utf-8'                   // 指定客户端在应答中支持的内容编码  
  8.       from='user@example.com'                             // 客户端JID  
  9.       hold='1'                                            // 指定服务器在会话过程中允许同时保持的最大数量  
  10.       rid='1573741820'                                    // 请求id  
  11.       to='example.com'                                    // 服务domain,对应JID中的domain  
  12.       route='xmpp:example.com:9999'                       // 该domain下具体的主机(一个域下可能有多个主机)  
  13.       ver='1.6'                                           // BOSH协议版本  
  14.       wait='60'                                           // 服务器允许hold住连接的等待时间(单位秒)  
  15.       ack='1'                                             // 表示客户端支持确认机制  
  16.       xml:lang='en'  
  17.       xmlns='http://jabber.org/protocol/httpbind'/>  
若将wait或hold中的一个置为0,那么长轮询将退化为传统轮询
 
2. BOSH会话创建应答
  1. HTTP/1.1 200 OK  
  2. Content-Type: text/xml; charset=utf-8  
  3. Content-Length: 128  
  4.    
  5. <body wait='60'                                           // 必须小于请求中指定的值  
  6.       inactivity='30'                                     // 若超出该期限没有客户端连接被保持则服务端中止会话(类似TCP超时机制)  
  7.       polling='5'                                         // 指定允许客户端最小轮询间隔(不低于<span class="s1">5</span>秒的轮询间隔)  
  8.       requests='2'  
  9.       hold='1'  
  10.       ack='1573741820'                                    // 对应rid  
  11.       accept='deflate,gzip'                               // 服务器支持的内容编码  
  12.       maxpause='120'                                      // 表示服务器支持临时会话暂停的最大长度  
  13.       sid='SomeSID'                                       // session id  
  14.       charsets='ISO_8859-1 ISO-2022-JP'  
  15.       ver='1.6'  
  16.       from='example.com'  
  17.       xmlns='http://jabber.org/protocol/httpbind'/>  


3. BOSH传输信息

 

  1. POST /webclient HTTP/1.1  
  2. Host: httpcm.example.com  
  3. Accept-Encoding: gzip, deflate  
  4. Content-Type: text/xml; charset=utf-8  
  5. Content-Length: 188  
  6.    
  7. <body rid='1249243562'  
  8.       sid='SomeSID'  
  9.       xmlns='http://jabber.org/protocol/httpbind'>  
  10.   <message to='contact@example.com'  
  11.            xmlns='jabber:client'>  
  12.     <body>Good morning!</body>  
  13.   </message>  
  14.   <message to='friend@example.com'  
  15.            xmlns='jabber:client'>  
  16.     <body>Hey, what's up?</body>  
  17.   </message>  
  18. </body>  

 

 

4. BOSH空应答

在一个等待周期里没有数据准备好,则应答一个空body

 

    1. HTTP/1.1 200 OK  
    2. Content-Type: text/xml; charset=utf-8  
    3. Content-Length: 64  
    4.    
    5. <body xmlns='http://jabber.org/protocol/httpbind'/>  
posted @ 2013-02-06 12:59  swjm119  阅读(484)  评论(0编辑  收藏  举报