原文链接:http://www.cnblogs.com/deepleo/p/Comet.html

一、背景介绍

传统web请求,是显式的向服务器发送http Request,拿到Response后显示在浏览器页面上。这种被动的交互方式不能满足对信息实时性要求高的应用,譬如聊天室、股票交易行情、在线游戏等。Ajax轮询虽然可以解决这个问题,但是会带来增加服务器负担、带宽浪费,并且这种实现方式不够优雅。而Comet技术就是为此而生的。

本文只探讨基于浏览器的web端服务器推技术。服务器推技术在现实应用中有一些解决方案,主要分两类:一类是需要浏览器额外安装插件,基于套接口传送信息或者是基于RMI、CORBA进行远程调用,另一类则无需浏览器安装任何插件,就是本文着重讲的HTTP长连接技术:Coment。Alex Russell(Dojo Toolkit 的项目 Lead)称这种基于 HTTP 长连接、无须在浏览器端安装插件的“服务器推”技术为“Comet”。

写本文的目的:网上的资料比较零碎,博客园的文章基本都是代码+代码,或者直接翻译别人的成果,而对于原理性的东西讲的很少。本文就是给有兴趣或者即将开发服务器推技术的程序员一个技术概览,摸清行内来龙去脉。我比较忌讳对一种新技术,上来就Focus到某个具体的技术上而不能自拔,盲人摸象。我们在定系统框架,敲定技术解决方案之前应该比较各个实现方案技术的优缺点,这样才能做出好的系统来。

二、Comet实现模型

1.HTTP Long Polling:基于 AJAX 的长轮询方式     众所周知,AJAX可以异步调用XMLHttpRequest对象发送HttpRequest,Javascript响应处理函数根据服务端返回的信息对HTML页面显示进行更新。而使用AJAX实现服务器推与传统AJAX应用的不同之处在于:

a.服务器端会阻塞请求直到有数据返回或者超时;

b.客户端JS响应函数在处理完服务端返回的信息后会再次发出请求,重新建立连接;

如图1所示,因为这种方案基于 AJAX,具有以下一些优点:请求异步发出;无须安装插件;IE、Mozilla FireFox 都支持 AJAX。

图1:基于 AJAX 的长轮询方式

2.HTTP Streaming:基于 Iframe 及 htmlfile 的流方式     通过在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。如图2所示。
图2. 基于流方式的服务器推模型

两种方案对比:

a.在对返回的数据处理方面:方案2(IFrame)返回的是对客户端javascript调用,,如“<script type="text/javascript">js_func(“data from server ”)</script>”。服务器端将返回的数据作为客户端 JavaScript 函数的参数传递;客户端浏览器的 Javascript 引擎在收到服务器返回的 JavaScript 调用时就会去执行代码。而方案1(AJAX)返回的是数据,通过JS可以很方便的操作DOM。

b.使用IFrame还有一个明显不足:IE、Morzilla Firefox 下端的进度栏都会显示加载没有完成,而且 IE 上方的图标会不停的转动,表示加载正在进行。不过这个问题已经被Google技术人员解决,并应用到Gtalk中,解决方案是:ActiveX 控件解决 iframe 请求长连接时 IE 的加载显示问题,原文地址:“What else is burried down in the depth’s of Google’s amazing JavaScript?

三、实际开发时应该注意的问题

对于一个实际的应用而言,系统的稳定性和性能是非常重要的。将 HTTP 长连接用于实际应用,很多细节需要考虑。

1.不要在同一客户端同时使用超过两个的 HTTP 长连接

这个是由于HTTP 1.1 规范中规定:客户端不应该与服务器端建立超过两个的 HTTP 连接,新的连接会被阻塞。所以,在设计上考虑让多个 frame(AJAX)共用一个长连接。

2.服务器端的性能和可扩展性     一般的WEB服务器是为每个连接创建一个线程,所以在使用Comet时,服务器要维护大量并发,长期存在的长连接。在这种背景下,就需要服务器负载均衡和集群技术,或者在服务端做一些优化。这篇文章:http://rdc.taobao.com/blog/cs/?p=1062的测试表明:200万个Http长连接占用率19G服务器内存,一个大约9kb;所以,你可以算一下你的服务器最多可以维护多少个长连接。

3.控制信息与数据信息使用不同的 HTTP 连接

用长连接时,存在一个很常见的场景:客户端网页需要关闭,而服务器端还处在读取数据的堵塞状态,客户端需要及时通知服务器端关闭数据连接。服务器在收到关闭请求后首先要从读取数据的阻塞状态唤醒,然后释放为这个客户端分配的资源,再关闭连接。

所以在设计上,我们需要使客户端的控制请求和数据请求使用不同的 HTTP 连接,才能使控制请求不会被阻塞。

在实现上,如果是基于 iframe 流方式的长连接,客户端页面需要使用两个 iframe,一个是控制帧,用于往服务器端发送控制请求,控制请求能很快收到响应,不会被堵塞;一个是显示帧,用于往服务器端发送长连接请求。如果是基于 AJAX 的长轮询方式,客户端可以异步地发出一个 XMLHttpRequest 请求,通知服务器端关闭数据连接。

4.在客户和服务器之间保持“心跳”信息

客户端不知道何时服务器才有数据传送。服务器端需要确保当客户端不在状态(工作)时,释放为这个客户端分配的资源,防止内存泄漏。因此需要一种机制使双方知道大家都在正常运行。

四、Comet框架介绍     由于Comet早在2006.2月就提出来了,所以并不是什么新鲜玩意,框架还是很多的,譬如:Dojox.cometd, Pushlet,SingalR。

Dojox.cometd:Comet概念的的提出者Alex Russel主导的Dojo项目分支,Dojo 基金会提出了 Bayeux 协议用来标准化 Comet 应用中客户端和服务器端之间的通信。Dojox.cometd 实现了 Bayeux 协议的客户端部分,使用 HTTP 长轮询来作为数据的传输通道。

Pushlet:基于HTTP流,而不是AJAX长轮询。一个开源的 Comet 框架,Pushlet 使用了观察者模型:客户端发送请求,订阅感兴趣的事件;服务器端为每个客户端分配一个会话 ID 作为标记,事件源会把新产生的事件以多播的方式发送到订阅者的事件队列里。貌似只支持Java。

SingalR:基于AJAX长轮询。ASP.NET团队开发的一个开源的.net framework库和Jquery插件。集成的客户端与服务器库,基于浏览器的客户端和基于 ASP.NET 的服务器组件可以借助它来进行双向多步对话。

五、SingalR的MVC4实践

1.安装与运行环境:(Nuget) install-package Microsoft.AspNet.SignalR ,注意:PM>后面不要有空格。

或者到GitHub上下载源码:https://github.com/SignalR/SignalR

这里顺便提一下,SingalR服务端需要支持的OS:

  • Windows Server 2012
  • Windows Server 2008 r2.
  • Windows 8
  • Windows 7
  • Windows Azure

.net framework4,4.5。WebSocket必须是4.5.

IIS7,7.5 ,integrated Mode,而不是classic Mode, WebSockets必须IIS8。更加详尽的说明,请自行参考:http://www.asp.net/signalr/overview/getting-started/supported-platforms

2.核心实现:

首先,我们需要引用SignalR,用Nuget不需要自己手工添加,应为你的asp.net mvc项目自动添加好一切。

服务端Library:

Microsoft.AspNet.SignalR.Core Microsoft.AspNet.SignalR.Owin Microsoft.AspNet.SignalR.SystemWeb Owin Newtonsoft.Json

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
 
namespace DeepleoComet
{
    public class ChatHub : Hub
    {
        public void Send(string name, string message)
        {
            // Call the addNewMessageToPage method to update clients.
            Clients.All.addNewMessageToPage(name, message);
        }
    }
}

客户端的Jquery插件:

jquery.signalR-1.1.3.min.js.

@{
    ViewBag.Title = "Chat";
}
 
<h2>Chat</h2>
 
<div class="container">
    <input type="text" id="message" />
    <input type="button" id="sendmessage" value="Send" />
    <input type="hidden" id="displayname" />
    <ul id="discussion">
    </ul>
</div>
 
@section scripts {
    <script src="~/Scripts/jquery.signalR-1.1.3.js"></script>
    <script src="~/signalr/hubs"></script>
    <script>
        $(function () {
            var chat = $.connection.chatHub;
            chat.client.addNewMessageToPage = function (name, message) {
                $('#discussion').append('<li><strong>' + htmlEncode(name)
                    + '</strong>: ' + htmlEncode(message) + '</li>');
            };
          
            $('#displayname').val(prompt('Enter your name:', ''));
            $('#message').focus();
            $.connection.hub.start().done(function () {
                $('#sendmessage').click(function () {
                    chat.server.send($('#displayname').val(), $('#message').val());
                    $('#message').val('').focus();
                });
            });
        });
      
        function htmlEncode(value) {
            var encodedValue = $('<div />').text(value).html();
            return encodedValue;
        }
    </script>
}

实现效果:

开两个页面:http://localhost:11968/ ,分别键入name,就可以实现一个简单的聊天室功能了。

六、题外话:Comet的替代品:Html5的WebSocket

在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。

真是相见恨晚啊,才知道还有这么个东西,居然Web端也有了全双工的Socket,貌似有个socket.io还支持IE6,我和我的小伙伴们都惊呆了。

比较好的关于WebSocket文章:http://www.cnblogs.com/wei2yi/archive/2011/03/23/1992830.html

参考资料

1.原理:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

2.DOJO原理与实践:http://www.ibm.com/developerworks/cn/web/wa-lo-w2fpak-comet/

3.淘宝200W长链接测试与优化:http://rdc.taobao.com/blog/cs/?p=1062

4.长连接百科:http://baike.baidu.com/view/2831907.htm

5.博客园Comet专题:http://kb.cnblogs.com/page/112185/

6. Jetty+Dojo+Tomcat:http://blog.csdn.net/garfier/article/details/5942826

7.SingalR官网:http://signalr.net/

8.Singal辅导:http://www.asp.net/signalr

Comet:基于 HTTP 长连接的“服务器推”技术解析的更多相关文章

  1. Comet:基于 HTTP 长连接的“服务器推”技术

    “服务器推”技术的应用 请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档.教程.论坛.blog.wiki 和新闻.任何 Ajax 的新信息都能在这里找到. c ...

  2. 转载:Comet:基于 HTTP 长连接的“服务器推”技术

    转自:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无须客 ...

  3. [转载] Comet:基于 HTTP 长连接的“服务器推”技术

    转载自http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ “服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工 ...

  4. Comet:基于 HTTP 长连接的“服务器推”技术(转载)

    “服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工作.这种方式并不能满足很多现实应用的需求,譬如: 监控系统:后台硬件热插拔.LED.温度.电压发生变化: 即时通信 ...

  5. 【转】Comet:基于 HTTP 长连接的“服务器推”技术

    原文链接:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无 ...

  6. comet基于HTTP长连接技术(java即时通信,推送技术详解)

    服务器推送技术的基础思想是将浏览器主动查询信息改为服务器主动发送信息,服务器发送一批数据,浏览器显示消息,同时保证与服务器的连接,当服务器需要再一次的发送数据,浏览器显示数据并保持连接. comet基 ...

  7. HTTP长连接实现“服务器推”的技术

    HTTP长连接实现“服务器推”的技术快速入门及演示示例 在我的印象里HTTP是一种“无状态的协议”,也就是不知道以前请求的历史,无法保留上一次请求的结果.Cookie的诞生,弥补了这个不足,浏览器可以 ...

  8. ASP.NET MVC 长连接(服务器推)完整实现

    1.什么是"服务器推"(百科来一波)? 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工作.这种方式并不能满足很多现实应用的需求,譬如: 监控系统:后台硬件热插拔.L ...

  9. Comet技术详解:基于HTTP长连接的Web端实时通信技术

    前言 一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Ser ...

随机推荐

  1. java接口和抽象类

    关于接口 1.创建一个接口,需要使用interface关键字. 2.实现一个接口,需要使用implements关键字. 3.接口的成员属性都是静态常量(默认public static final). ...

  2. 使用php脚本查看已开启的扩展

    php安装时会将扩展包编译进去,对于一个正在运行中的数据库,查看php的扩展开启状况,第一种方式是通过配置文件查看,另外是通过phpinfo函数查看所有的配置,另外是使用php内置函数来查看,通过脚本 ...

  3. Kafka单机环境部署

    前面说过Kafka集群环境的部署,现在主要说一下在本地测试中Kafka单机环境的部署,和前面一样首先保证zookeeper服务的正常运行,然后解压并释放kafka安装包,并放到指定位置: tar -x ...

  4. 手动设置Windows7锁屏界面背景

    windows7系统安装之后锁屏.关机界面.开机欢迎界面都是系统默认的背景,其实这些背景就像桌面壁纸一样是可以更改的,如果没有修改过的话,按下面步骤就可以修改了. 首先选择一张喜欢的背景图片,分辨率不 ...

  5. NSOJ A fairy tale of the two(最小费用最大流、SPFA版本、ZKW版本)

    n,m<=20,给两个n×m布尔矩阵,每次操作可将第一个矩阵的2个相邻元素互换.输出最少操作次数使得两个矩阵完全一样. 比赛的时候想过按照二分图完美匹配的类似做法构图,不过想到边太多以及卡各种题 ...

  6. MFC Initinstance中DoModal()返回-1

    新建一个基于对话框的MFC应用程序,在App的Initinstance中调用对话框DoModal()来显示对话框,这是框架的内容,应用程序框架生成的全部是正常的. 当把我对话框的资源文件提取到一个资源 ...

  7. Java实现注册邮箱激活验证

    邮件发送servelet实现 package com.xbs.register.main; import java.io.IOException;import java.util.Date;impor ...

  8. [USACO07MAR]黄金阵容均衡Gold Balanced L…(洛谷 1360)

    题目描述 Farmer John's N cows (1 ≤ N ≤ 100,000) share many similarities. In fact, FJ has been able to na ...

  9. SQLServer视图

    视图简介:通过定义 SELECT 语句以检索将在视图中显示的数据来创建视图.SELECT 语句引用的数据表称为视图的基表.在SQL Server 2005系统中,可以把视图分为3种类型,即标准视图,索 ...

  10. WhaleSong

    Chasingwaves by myself in theocean of endless sorrow Makingwishes that i will find myherd tomorrow 5 ...