最近一个项目里要用到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;
}
二.客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
function ConnectHandler() {
...
var result = data;
if (result != "") {
//当收到服务器信息后再次发起连接
ConnectHandler();
}
}
三.当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。
//如果有给对方的消息则推送.然后标记已读
StringBuilder builderMsg = new StringBuilder();
StringBuilder builderIds = new StringBuilder();
if (listMsg != null && listMsg.Count > 0)
{
...
大致上就是根据上面的理论来操作的.就像是一个搬运工,搬完了东西就跑去包工头那里等.包头工手上有东西了马上给搬运工.这个搬运工等的时候就是长连接.传统的ajax是不断询问,相当于搬运工手里没东西也要不停来回跑.
示例DEMO
先看个效果吧
1.新建立一个登录页
你的姓名: <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();
});
用户发送一条消息传给处理页Handler.ashx,处理页会阻塞此连接(相当于保持连接).然后保存此消息到数据库,成功返回应答告诉用户消息已经保存,可以再输入下一条消息.这就像QQ信息没发出时[发送]按钮是灰色一样的道理.
当有用户消息时,系统会输出消息
else
{
//获取所有当前请求者的消息并返回
IList<IMMessage> listMsg = IMMessage.GetMessageListBySender(msg.Sender);
string strMsg = string.Empty;
//如果有给对方的消息则推送.然后标记已读
StringBuilder builderMsg = new StringBuilder();