最近对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 代码如下:
然后新建一个WebService.asmx文件,用于发数据,主要是获取锁对象,然后解锁。WebMethod 如下:
现在浏览器一和我们的web服务连接好了,但是没有数据。我们利用web services发送一条数据“hello”,当我们单击启动按钮之后,FF马上就收到了数据:
再发一条:
上面访问Default.aspx 页面要用Firefox,不能用IE,不然页面上不会显示信息。通过测试发现实际上已经拿到数据,但是就是不现实,一定要关掉连接才会显示,不知道为什么。
上面的代码没有什么实用,只是希望大家也来讨论一下Comet这种新的开发模式。
附Gmail-chat抓包图:
再来看看我们试验产生的数据包:
对上面gmail-chat的数据包,发现一模一样。
还记得前两年流行聊天室的时候出现一种叫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中。{
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();
}
}
}
}
}
然后新建一个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 int SendMessage(string message)
{
if (Application["holy"] == null)
return 0;
lock (Application["holy"])
{
((Message)Application["holy"]).Text = message;
Monitor.PulseAll(Application["holy"]);
}
return 1;
}
public class Message
{
private string text;
public string Text
{
get { return text; }
set { text = value; }
}
public Message()
{
}
}
编译,首先用FF访问Default.aspx页面,然后在打开webservice页面(就是WebService.asmx
)如图:{
private string text;
public string Text
{
get { return text; }
set { text = value; }
}
public Message()
{
}
}
现在浏览器一和我们的web服务连接好了,但是没有数据。我们利用web services发送一条数据“hello”,当我们单击启动按钮之后,FF马上就收到了数据:
再发一条:
上面访问Default.aspx 页面要用Firefox,不能用IE,不然页面上不会显示信息。通过测试发现实际上已经拿到数据,但是就是不现实,一定要关掉连接才会显示,不知道为什么。
上面的代码没有什么实用,只是希望大家也来讨论一下Comet这种新的开发模式。
附Gmail-chat抓包图:
再来看看我们试验产生的数据包:
对上面gmail-chat的数据包,发现一模一样。