======================================================
注:本文源代码点此下载
======================================================
comet(http 请求长连接) 之 ajax 长查询 简单实现。
这几天看到几篇关于http 长连接的文章,之前做过一个简单webim 采用ajax定时查询,效率一般,请求一多 iis 日志每天大概有80m左右。在线人数在40人左右(基本和挂qq一样)。
今天特意研究了一下http 的长连接。有了一点点成果。现放出来大家一起讨论一下。
不清楚长连接请点这里。
1.客户端请求
script type="text/javascript">
var httprequest;
function createxmlhttprequest()
{
if(window.xmlhttprequest)
{
httprequest=new xmlhttprequest();
}
else if(window.activexobject)
{
httprequest=new activexobject("microst.xmlhttp");
}
}
function send()
{
document.getelementbyid("test").innerhtml="等待返回信息";
createxmlhttprequest();
if(httprequest!=null)
{
httprequest.onreadystatechange=showmessage;
httprequest.open("get","handler.ashx?name="+escape("leon")+"&m"+math.random());
httprequest.send();
}
}
function showmessage()
{
if(httprequest.readystate==4&&httprequest.status==200)
{
if(httprequest.responsetext.length>0)
{
alert(httprequest.responsetext);//收到信息
//如果有信息返回 重新发送请求 递归
send();
}
}
}
/script>
2.服务的如何hold请求
code
public class handler : ihttphandler
{
private bool ok = true;
public void processrequest(httpcontext context)
{
ok = true;
while (ok)//超时设置ok为false即可
{
//循环检查是否有信息存在
check();
//防止循环太频繁
system.threading.thread.sleep(1000);
}
}
private void check()
{
listmessage> list = new listmessage>();//信息列表
string str = "";
lock (im.mlist)
{
if (im.mlist.count > 0)
{
foreach (message m in im.mlist)
{
if (m.username == httpcontext.current.request["name"].tostring())
{
list.add(m);
str = m.messagecontent;
break;
}
}
if (list.count > 0)
{
foreach (message m in list)
{
im.mlist.remove(m);
}
}
//收到信息 循环结束
ok = false;
if (list.count > 0)
{
//推信息
httpcontext.current.response.write("收到信息:" + str);
}
}
}
}
public bool isreusable
{
get
{
return false;
}
}
}
============================================================
示例代码:fck.rar
生命是一个过程,可悲的是这个过程不能够重来。
绿色通道:好文要顶关注我收藏该文与我联系
posted on 2009-10-10 14:08 leon yang 阅读(4753) 评论(39)编辑 收藏
feedback:
1793746
生命是一个过程,可悲的是这个过程不能够重来。
可喜的是他也不需要重来
回复 引用 查看
引用沛沛:
生命是一个过程,可悲的是这个过程不能够重来。
可喜的是他也不需要重来
恭喜你
回复 引用 查看
朋友,你的代码不是http长连接吧,是http多连接
http长连接的关键是在服务端
回复 引用 查看
利用httphandler来"hold"貌似是一个很不错的方法.
ps:"im"这个变量是从哪跑出来的?
回复 引用 查看
用异步httphandler吧,性能有质的飞跃。
回复 引用 查看
#6楼[楼主]
@rosanshao
请仔细看完服务端代码。或者下载示例代码自己测试。
注意这里
public void processrequest(httpcontext context)
{
ok = true;
while (ok)//超时设置ok为false即可
{
//循环检查是否有信息存在
check();
//防止循环太频繁
system.threading.thread.sleep(1000);
}
}
//while循环代码不停止 当前request 是不会结束的。
也就是说请求得不到服务器的response 所以连接时一直保持的 除非超时。
回复 引用 查看
#7楼[楼主]
@careyson
im这个在示例代码里面的。
回复 引用 查看
引用rosanshao:
朋友,你的代码不是http长连接吧,是http多连接
http长连接的关键是在服务端
同意,我感觉这也不叫长连接,只是通过循环去检查有无信息,好像把前台通过ajax的轮询搬到了后台。
回复 引用 查看
#9楼[楼主]
@coolin
请仔细看这片介绍。
http://www.cnblogs.com/happyday56/archive/2009/06/10/1500427.html
回复 引用 查看
response.write后并没有flush啊,内容不会写到客户端吧。。。
回复 引用 查看
#11楼[楼主]
@q.lee.lulu
为什么write后面要response.flush??
write的时候 客户端与服务端 任然是保持连接的 客户端为什么会收不到呢?
请自己测试示例代码。
回复 引用 查看
#12楼[楼主]
普通的请求 服务端可能1秒之内就处理完了 客户端马上收到response信息,连接当然就断开了。
这里的长连接就是要拖延服务端的response
加长服务端处理的时间 客户端得不到服务端的response 当然只能一直与服务端保持连接。
回复 引用 查看
厄~~~看到ok=false了
你这个根本不是长连接,在服务器收到信息后连接就完成了。。。
回复 引用 查看
2009-10-10 20:42 | jeffrey zhao
不异步是不行滴。
回复 引用 查看
不错,我已经根据这个做了一个分布式的im出来了,多交流
回复 引用 查看
#16楼[楼主]
@q.lee.lulu
基于长轮询的服务器推模型
回复 引用 查看
#17楼[楼主]
@omeweb
恩 一起交流。
回复 引用 查看
@leon yang
你贴的图上面写着的是长轮询,在一次会话过程中也是要不停的发送新的请求的。
长连接我的理解是发起会话,一直到他退出会话,这个连接都是一直保持连接状态的。
回复 引用 查看
#19楼[楼主]
引用q.lee.lulu:
@leon yang
你贴的图上面写着的是长轮询,在一次会话过程中也是要不停的发送新的请求的。
长连接我的理解是发起会话,一直到他退出会话,这个连接都是一直保持连接状态的。
这样子不是有悖http协议吗?这种超长的连接也是不适合互联网的吧。这里的长连接是为了减少客户端得频繁request.
回复 引用 查看
好像不是一个长连接,
服务器会不会超时啊?
回复 引用 查看
connection:keep-live
改造一下,不行?
或者藏个flash,tcp
回复 引用 查看
while (ok) 改为 while (response.isclientconnected)
好点
回复 引用 查看
2009-10-11 03:04 | erer[未注册用户]
iis的连接数是有限的 这样长时间占用连接好吗?
回复 引用
楼主的意思长连接就是长时间的连着服务器,等到信息读取完毕然后断开?
回复 引用 查看
2009-10-11 10:06 | 毛毛鱼[未注册用户]
我的毕业设计做的就是这个东西,核心代码和楼主的差不多。建议楼主可以用些事件代理,会更加方便。
回复 引用
#26楼[楼主]
@在别处
请看这篇关于comet的介绍
http://www.cnblogs.com/happyday56/archive/2009/06/10/1500427.html
回复 引用 查看
#27楼[楼主]
@毛毛鱼
呵呵,我只是做了一个简单示例 还没有深入研究 暂时记录下来 以后有时间再深入研究。
回复 引用 查看
#28楼[楼主]
@erer
我想这个应该不需要去担心吧。
gmail+gtalk 都有应用。
回复 引用 查看
2009-10-11 11:57 | 毛毛鱼[未注册用户]
@leon yang
在codeplex有个comet的.net实现,你可以下载下来研究下。
回复 引用
引用leon yang:
@在别处
请看这篇关于comet的介绍
http://www.cnblogs.com/happyday56/archive/2009/06/10/1500427.html
此内容很久以前就见过,只是觉得您现在的这个while+sleep的设计似乎不那么合理,不实时估计效率也不很高。
回复 引用 查看
2009-10-11 13:41 | 毛毛鱼[未注册用户]
@在别处
可以使用多个线程,在线程中while+sleep保证实时和效率。
回复 引用
做个记号
回复 引用 查看
被虐了.
回复 引用 查看
引用leon yang:
@q.lee.lulu
为什么write后面要response.flush??
write的时候 客户端与服务端 任然是保持连接的 客户端为什么会收不到呢?
请自己测试示例代码。
response.flush可以将缓冲区内容立即送出。
回复 引用 查看
#35楼[楼主]
@normren
不适合ajax方式。ajax请求客户端收不到的(ie中)。你可以自己测试下。
---------------------------------------------
mozilla firefox 提供了对 streaming ajax 的支持, 即 readystate 为 3 时(数据仍在传输中),客户端可以读取数据,从而无须关闭连接,就能读取处理服务器端返回的信息。ie 在 readystate 为 3 时,不能读取服务器返回的数据,目前 ie 不支持基于 streaming ajax。
----------------------------------------------
回复 引用 查看
不支持ie的确头大啊,这样应用可能就小很多了,有的新的解决方案吗。
回复 引用 查看
2009-11-18 01:52 | nikeaa[未注册用户]
http://www.cnblogs.com/images/cnblogs_com/leon_yang/leon1.gif
这个框架能分享一份吗?
zhdqcn@gmail.com
多谢
回复 引用
#38楼[楼主]
@nikeaa
不好意思。暂时还没有做出一个完整的框架。
回复 引用 查看
谢了我用这个方法已经做了个跟qq差不多的im了差多对多聊天弄弄就搞定了
回复 引用 查看
注册用户登录后才能发表评论,请 登录 或 注册,返回博客园首页。
最新it新闻:
·android平台12月广告浏览份额51.6% 超越ios
» 更多新闻...
最新知识库文章:
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/