Live

  博客园 :: 首页 :: 联系 :: 订阅 订阅 :: 管理
  4 Posts :: 1 Stories :: 55 Comments :: 0 Trackbacks
      最近对Google很感兴趣,特别是Gmail中实现的chat功能。web IM实际上一点也不陌生,不过大多数都比较慢,可能还是归根于传统的pull data的模式,为了达到实时,只有提高pull的频率,不过这始终不是办法。并且很浪费资源,因为即使没有你要的数据,你也会一直在请求。回头看 Gmail中的Chat程序,发现很快,基本上和使用GTalk客户端差不多,经过抓包分析,发现并不是定时去请求拿数据。
     还记得前两年流行聊天室的时候出现一种叫server push的东西,主要是实现从服务器端推数据到浏览器,以此来达到无刷新的聊天室。这两年开始流行Ajax,基于Ajax实现的聊天室也多了起来,不过实际上还是定时去请求服务器。
     对于这类IM软件来说如果能实现服务器直接push 数据到浏览器上,应该是一个很好的方案。网上google了一下,发现国外已经有人提出一个叫Comet的概念。来看看Comet和Ajax的不同之处:

当然,Comet不能取代Ajax,但是Comet的应用范围应该也非常广,比如上面说的IM软件,聊天室,证券系统等等实时性比较高的应用。目前比较成功的应用有gamil还有meebo(www.meebo.com)。
      这种服务器推数据的方式,应该要保持一个长时间的浏览器到服务器的连接,目前还不清楚gmail的实现方式,自己模拟了一个。实现浏览器访问一个web服 务器,一直处于联机状态,如果有数据就把上把数据推倒浏览器上,这里我们用WebServices来发数据。
原理是用IIS作服务器,客户请求之后在Page_Load不要返回,让浏览器一直处于下载状态。我们的Default.aspx 代码如下:
protected void Page_Load(object sender, EventArgs e)
    {
        if(Application["holy"]==null)
            Application.Add("holy",new Message());

        while (true)
        {
            lock (Application["holy"])
            {
                while (Monitor.Wait(Application["holy"]))
                {
                    Message message=(Message)Application["holy"];
                    if (message.Text != string.Empty)
                    {
                        this.Response.Write(message.Text+"\n");
                        this.Response.Flush();
                    }
                }       
            }
        }
    }
里面是一个无穷循环,进去之后线程被挂起,锁对象放在Application中。
然后新建一个WebService.asmx文件,用于发数据,主要是获取锁对象,然后解锁。WebMethod 如下:
[WebMethod]
    public int SendMessage(string message)
    {
        if (Application["holy"] == null)
            return 0;

        lock (Application["holy"])
        {
            ((Message)Application["holy"]).Text = message;
            Monitor.PulseAll(Application["holy"]);
        }
        return 1;
    }
最后Message类是用来传递消息的,同时也是锁:
public class Message
{
    private string text;

    public string Text
    {
        get { return text; }
        set { text = value; }
    }

    public Message()
    {
    }
}
编译,首先用FF访问Default.aspx页面,然后在打开webservice页面(就是WebService.asmx )如图:

现在浏览器一和我们的web服务连接好了,但是没有数据。我们利用web services发送一条数据“hello”,当我们单击启动按钮之后,FF马上就收到了数据:




再发一条:


上面访问Default.aspx 页面要用Firefox,不能用IE,不然页面上不会显示信息。通过测试发现实际上已经拿到数据,但是就是不现实,一定要关掉连接才会显示,不知道为什么。
上面的代码没有什么实用,只是希望大家也来讨论一下Comet这种新的开发模式。
附Gmail-chat抓包图:

再来看看我们试验产生的数据包:

对上面gmail-chat的数据包,发现一模一样。
posted on 2006-08-08 14:37 一唯 阅读(4416) 评论(49)  编辑 收藏 网摘 所属分类: IM

Feedback

#1楼 2006-08-08 14:51 aspnetx      
天啊
原来还不好使呢啊
建议楼主看一下asp.net控件的生命周期
或许能解答你的问题,这里一两句话我怕描述不清楚

也可能是楼主的代码让我产生误解,怎么看好象都是原来的pull模式.即使这个方案真的可行的话,dudu不知道会怎么想,前一阵子他说博客园的连接数一大于2000就出现性能问题.我想用这个东西,因为一直有个线程在那挂着,所以,就不是靠改善程序能解决的了的吧,完全会有2000的多少倍的现成一直在那消耗服务器的资源.

以上纯熟个人见解.

  回复  引用  查看    

#2楼[楼主] 2006-08-08 15:09 一唯      
@aspnetx
嘿嘿,工作原因才开始学.Net。很多都不懂,特别是asp.NET。Comet这个东西是一个叫Alex的人提出的,至于后面那段代码嘛,我胡思乱想的啦。
不过这种开发模式确实很有趣,我想应该会像Ajax那样风靡。需要保持一个连接确实恐怖,不过可以确定的是gmail中的Chat确实保持了一个连接,国外有人说是利用一个ActiveX实现的,叫做“htmlfile”,不是很清楚。
另一个应用www.meebo.com可以明显地看出使用了某种负载均衡方案。
至于google怎么处理就不知道了。

我那段代码让大家见笑了。但是并不是pull方式,客户段第一次去请求之后就一直保持了那个连接,以后如果没有数据,就不发数据给浏览器,一旦有数据了,就马上把数据推至浏览器。并不是定时去请求,看有没有数据。(第一次请求应该是必要的吧,不然连接怎么建立^_^)

  回复  引用  查看    

看起来gmail并不是使用这种模式的哟
  回复  引用    

#4楼 2006-08-08 16:37 雨玲珑      
如果用户点一下停止不知道会咋样,呵呵
  回复  引用  查看    

#5楼[楼主] 2006-08-08 17:02 一唯      
@goodspeed.com.cn
不是Gmail,而是Gmail中的Chat模块。可以确定是一直保持一个连接。用Ethereal抓包会发现,开始的时候从你这里产生一个Http Get到google的服务器上,之后就没有再进行Http 请求,如果你的好友不停的发消息给你,服务器就把消息push给你。(我贴一张我抓包的图放在文章后面)


@雨玲珑
点一下就挂了。实际应用的话不会把这个连接这么表现给用户,用户也不能直接控制,可以用一个隐藏的iframe,或者用ActiveObject("htmllife")专门用来传输数据,用户交角度是看不出来的。

  回复  引用  查看    

#6楼 2006-08-08 17:07 发仔      
示例图片能不能不要小日本语言啊
  回复  引用  查看    

#7楼 2006-08-08 17:33 小蔡[未注册用户]
呵,都返朴归真了。
  回复  引用    

#8楼 2006-08-08 17:42 海蓝      
没有研究过Comet或GMail的chat功能,但从楼主的试验过程来看,用户多了性能就会是个大问题。为每个客户端保持一个连接绝对是个噩梦!光是内存开销就足以让服务器宕机了。至少要在服务器端使用连接池,就象ADO.NET的做法那样
  回复  引用  查看    

#9楼 2006-08-08 17:55 Mango      
Push mail就是这样做的,他们好象认为连接是用不完的,是无穷无尽的资源,哈哈!总有一天,在互联网上的http总是连接的,而不象现在这样非连接的,那我们还要http做什么,回到TCP吧。
  回复  引用  查看    

#10楼[楼主] 2006-08-08 17:57 一唯      
@小蔡
很多东西不是不好,一定要在一定的情况下再回发光,就像Ajax^_^


@海蓝
赞成,所以说这种技术不是用来取代传统client pull技术的,而是他的补充。从这个角度来看,连接数量就不是问题了。现在开发模式被分为所谓的B/S,与C/S,我想这也是一个原因吧。那么目前的C/S怎么解决连接数量问题呢?可以设想,一旦这种技术成熟,将大大增强基于浏览器系统的应用面。

@Mango
呵呵,很多东西都比较奇怪。就拿http来说,一个建立在面向连接协议上的无连接协议......不过当时建立Http的人也想不到会发展到这个样子^_^。
不过现在好像开始大整合了,期待没有什么b/s,c/s之分的那一天。撤远了:)

  回复  引用  查看    

#11楼 2006-08-08 21:31 amou[未注册用户]
不知道抓包用的是什么工具呢?能不能抓talk的包啊?我很笨,帮帮我~~~
  回复  引用    

#12楼 2006-08-08 21:34 mikespook      
记得5年前,JAVA刚开始火起来没几年的时候~~看过一些资料是用JSP写聊天室~~既是这种方式,让浏览器load一个永远没有结束的页面,并且保证服务器端不会超时~~~随时有内容,随时push到stream里~~

跟ajax一样,其实还是古老的技术~

  回复  引用  查看    

#13楼 2006-08-08 21:57 代码乱了      
其实这样的技术的确有很多地方是很需要的,也很吸引人
期待有成熟的技术出现

  回复  引用  查看    

#14楼 2006-08-08 21:59 jillzhang      
其实什么技术都是一样,旧瓶装新酒!

  回复  引用  查看    

http://www.orbeon.com/blog/2006/03/01/kudos-to-google-for-the-google-talk-integration-in-gmail/
  回复  引用    

技术都是会越来越好的,一起进步吧.
  回复  引用    

#17楼[楼主] 2006-08-09 09:32 一唯      
@amou
我用的是Ethereal,以前也用过wpe,wpe使用简单,不过还是推荐用Ethereal,非常强大。能抓到所以目标网卡上收到的数据包,talk当然也能抓啊

  回复  引用  查看    

comet在aspnet我已经尝试过,
我在ie下是可以正常的,你最好开始的时候在response的buffer里面加上530个空格左右,让缓冲区充满,第一次能flush,就不会发生得到数据不显示的问题了.
希望对你有帮助

  回复  引用    

IE浏览器接收到一定数据的时候才会显示.所以我做的时候是刚连接的时候就输送了一些没有用的东西.这样下次发送的进候才可以显示
  回复  引用    

#20楼[楼主] 2006-08-09 11:23 一唯      
@ChuPaChuPs @lovebanyi
非常感谢,确实是缓冲的原因。
@ChuPaChuPs
你是怎么在ASP.Net下实现comet的?用我的方法好像没法拿到客户段反馈信息,比如说浏览器再发Request过来。
如果是浏览器是FF,好像可以利用multipart/x-mixed-replace这种Content-Type来实现分段flush数据。

  回复  引用  查看    

#21楼 2006-08-09 11:41 neozhu[未注册用户]
你是用什么工具捕获那些跟踪信息的
  回复  引用    

不客气,也只是小小的尝试,很多问题呢,
什么是客户端反馈信息啊,

  回复  引用    

#23楼[楼主] 2006-08-09 13:01 一唯      
@neozhu
是用一个叫Ethereal的抓包工具

@ChuPaChuPs
我是想怎么来判断客户端状态,比如掉线,消息发送失败等。我上面的那个demo实际上只有server推数据到客户端,没办法拿到客户端后面的请求信息。现在就想怎么实现双向实时通讯。

  回复  引用  查看    

我就试了聊天,
隐藏个iframe专门提交数据...

  回复  引用    

#25楼[楼主] 2006-08-09 16:10 一唯      
@ChuPaChuPs
能不能代码给我看看阿。参考一下
我的Email:songsong_520@hotmail.com
thx:)

  回复  引用  查看    

#26楼 2006-08-10 08:14 gozh2002
saw an example with a comet chatroom long time ago.
it is really just ajax + javascript event


  回复  引用    

#27楼 2006-09-05 11:19 cobalt[未注册用户]
@一唯
我是想怎么来判断客户端状态,比如掉线,消息发送失败等。我上面的那个demo实际上只有server推数据到客户端,没办法拿到客户端后面的请求信息。现在就想怎么实现双向实时通讯。

一个xmlhttp长连接保证server push,需要上传数据则在启动一个xmlhttp。

  回复  引用    

我用JAVA也做了类似的Server Push.

我加了一句 response.setContentType("multipart/x-mixed-replace;boundary=END");

当我用Firefox测试是,输出的时候是新的文本代替老的文本,但是用IE测试的时候,结果却是在老的文本之后追加新的文本,请问一下这是什么原因?

  回复  引用    

请你把程序倒过来跑可不..?

也就是让IE来做你的接收端,能像firefox那么爽吗??????????
发送端就无所谓了..

这个IE大老真的麻烦呀.......................

  回复  引用    

如果能行,麻烦你告诉我一声, 我的邮箱: willbe@126.com. QQ:378090719
  回复  引用    

@pear[匿名]
IE好像不支持multipart/x-mixed-replace类型

  回复  引用    

那IE的Server Push要怎么做?
  回复  引用    

关注中
IE的Server Push好象没法做!
还有pear,你的IE输出的内容没问题吗?我的连"--END"这些都输出来了,郁闷啊!

  回复  引用    

#34楼[楼主] 2006-10-10 18:05 一唯      
我上面的程序在IE中也可以运行的,只要先输出340个空格左右的数据把缓冲区填满。
  回复  引用  查看    

#35楼 2007-03-31 15:55 crazy[未注册用户]
关注中:
我也想知道怎么来判断客户端状态,比如掉线,消息发送失败等

  回复  引用    

#36楼 2007-04-06 04:00 LUKE[未注册用户]
HTTP://rd-program.blogspot.com

酄迎上我的BLOG查看COMET相關測試

  回复  引用    

lz的代码是不能实际中应用的!!!
  回复  引用    

#38楼 2007-07-26 17:55 整形[未注册用户]
整形
  回复  引用    

不知道抓包用的是什么工具呢
  回复  引用    

comet在aspnet我已经尝试过, 我在ie下是可以正常的
  回复  引用    

--引用--------------------------------------------------
comet在aspnet我已经尝试过, 我在ie下是可以正常的
--------------------------------------------------------

  回复  引用    

comet在aspnet我已经尝试过, 我在ie下是可以正常的
--------------------------------------------------------

--------------------------------------------------------

  回复  引用    

--引用--------------------------------------------------
pear[匿名]: 那IE的Server Push要怎么做?
--------------------------------------------------------

  回复  引用    

--引用--------------------------------------------------
crazy: 关注中:
我也想知道怎么来判断客户端状态,比如掉线,消息发送失败等
--------------------------------------------------------

  回复  引用    

#45楼 2008-01-24 21:46 (心)Shing Ye      
我找你很久了..请问如何实现的..我根据你的代码写了不行...一直在下载但是没有效果出来...我发了邮件给你了..可以快点回复我吗?谢谢了...急用啊..
  回复  引用  查看    

#46楼 2008-01-30 17:30 Dare[未注册用户]
--引用--------------------------------------------------
mikespook: 记得5年前,JAVA刚开始火起来没几年的时候~~看过一些资料是用JSP写聊天室~~既是这种方式,让浏览器load一个永远没有结束的页面,并且保证服务器端不会超时~~~随时有内容,随时push到stream里~~

跟ajax一样,其实还是古老的技术~
--------------------------------------------------------
没错,十年前的聊天室就已经用了这样的技术了

  回复  引用    

只有Firefox有效是因为IE不能同时对一个网站有2个以上的连接…… IE is draconian

The news on the client isn’t so good. Clients can’t make more than two HTTP connections to any box/subdomain (per spec). Firefox may not adhere to this limit. IE is draconian. The JavaScript code needs to know about this and deal with it—right down to peering with other browser instances and managing connections

http://www.windley.com/archives/2006/03/alex_russell_on.shtml

  回复  引用    

要求是什么。。。
  回复  引用    

不错不错
  回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 471092




相关文章:

相关链接: