Comet ajax长连接及demo
最近一个项目里要用到b/s即时通讯.又不想用第三方的(主要是怕有版权问题).于是自己研究一下,按传统的ajax定时轮询服务器来获取消息的办法的缺点就是不够实时,而且不停的查询造成服务器压力不小.
理论:
在网上找到一篇文章Comet:基于 HTTP 长连接的“服务器推”技术(http://www.ibm.com/developerworks/cn/web/wa-lo-comet/)
发现很不错.所以自己试着写了一个demo.主要实现下面的技术
一.服务器端会阻塞请求直到有数据传递或超时才返回。
bool flag = true;
//服务器阻塞.直到有消息返回
while (flag)
{
...
//信息已接收,返回应答
HttpContext.Current.Response.Write("state.savesuccess");
flag = false;
}
function ConnectHandler() {
...
var result = data;
if (result != "") {
//当收到服务器信息后再次发起连接
ConnectHandler();
}
}
//如果有给对方的消息则推送.然后标记已读
StringBuilder builderMsg = new StringBuilder();
StringBuilder builderIds = new StringBuilder();
if (listMsg != null && listMsg.Count > 0)
{
...
你的姓名: <asp:TextBox ID="txtSenderName" runat="server"></asp:TextBox> <br />
接收方姓名:<asp:TextBox ID="txtReciverName" runat="server"></asp:TextBox> <br />
<input type="button" value="登录" />
<script type="text/javascript">
$("input[value='登录']").click(function() {
location = "IM.aspx?Sender=" +encodeURI( $('#<%=txtSenderName.ClientID %>').val() ) + "&Reciver=" +encodeURI( $('#<%=txtReciverName.ClientID %>').val() );
});
</script>
2.新建立一个聊天界面IM.aspx
这里主要左边是一个在线会员列表,右边是聊天区
当登录页面后,系统马上会连接到处理页,看看是否有用户的消息.如果有则显示出来
[code=JScript]
//登录即请求
$(function() {
ConnectHandler();
});
else
{
//获取所有当前请求者的消息并返回
IList<IMMessage> listMsg = IMMessage.GetMessageListBySender(msg.Sender);
string strMsg = string.Empty;
//如果有给对方的消息则推送.然后标记已读
StringBuilder builderMsg = new StringBuilder();
StringBuilder builderIds = new StringBuilder();
if (listMsg != null && listMsg.Count > 0)
{
for (int i = 0; i < listMsg.Count; i++)
{
if (i == listMsg.Count - 1)
builderMsg.Append(listMsg[i].AutoID + "|" + listMsg[i].Sender + "|" + listMsg[i].Msg.Replace("|", "").Replace(",", ".") + "|" + listMsg[i].SendTime.ToString());
else
builderMsg.Append(listMsg[i].AutoID + "|" + listMsg[i].Sender + "|" + listMsg[i].Msg.Replace("|", "").Replace(",", ".") + "|" + listMsg[i].SendTime.ToString() + ",");
}
HttpContext.Current.Response.Write(builderMsg.ToString());
flag = false;
}
}
else if (result.indexOf("|") != -1) {
var id = result.split('|')[0];
var element = $("#showmsgwindow").find("div[id='msg_" + id + "']");
if (element.length == 0) { //判断是否已经输出到页面
$("#showmsgwindow").append("<div id='msg_" + id + "' style='margin:3px 0'><b>" + result.split('|')[1] + "</b> (" + result.split('|')[3] + ") 说:<br/>" + result.split('|')[2] + "</div>");
delmsg(id);//标记为已读,不会再输出到页面
}
}
//定时器,检测会员在线情况
private System.Threading.Timer timeAuto;
protected void Application_Start(object sender, EventArgs e)
{
//定时器 间隔10秒 随应用程序启动
timeAuto = new System.Threading.Timer(new System.Threading.TimerCallback(CheckUserOnlie), this, 0, 20 * 1000);
}
private void CheckUserOnlie(object obj)
{
OnlineUser.CheckOnlineUser();
}