代码改变世界

用IHttpAsyncHandler实现Comet

2010-05-27 00:36  Kevin-wang  阅读(4224)  评论(7编辑  收藏  举报

实现功能:登录、获取用户列表、退出;JS库采用jQuery1.32
解决方案
image
运行时的效果图:
输入帐号后,点击“Login”按钮后显示当前在线的用户列表,点击“Logout”按钮后当前用户退出后向其它在线用户推送新的在线用户列表;
image 
Default.aspx页面引用的两个js脚本,jQuery1.3.2,WebIM.js;

<script src="Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="Scripts/WebIM.js" type="text/javascript"></script>

HTML DOM代码如下:

    <asp:Label ID="Label1" runat="server" Text="帐号"></asp:Label>
    
<input id="txtLoginID" type="" /><input id="btnLogin" type="button" value="Login" /><input
        
id="btnLogout" type="button" value="Logout" />
    
<br />
    
<div id="divUserList">
    
</div>
    
<br />
    广播内容:
    
<input type="text" id="content" /><br />
    消息记录:
    
<div id="divResult">
    
</div>
    
<input type="button" id="btnSend" value="广播" />


WebIM.js脚本

/// <reference path="jquery-1.3.2.min.js" >
$(document).ready(function() {
    
//状态,代表是否登录
    var _logined = false;

    
//登录,登录成功后,获取在线用户列表,
    function login() {
        $.post(
"comet_broadcast.asyn", { action: 'login', uid: $("#txtLoginID").val() },
        
function(data, status) {
            
if (data == "OK") {
                _logined 
= true;
                getuserlist();
            }
        });
    }

    
//获取在线用户列表,获取列表后,进入消息等待
    function getuserlist() {
        $.post(
"comet_broadcast.asyn", { action: 'getuserlist', uid: $("#txtLoginID").val() },
        
function(data, status) {
            
//alert('getuserlist' + data);
            var result = $("#divResult");
            result.html(result.html() 
+ "<br/>" +"用户列表:" +data);
            wait();
        });
    }

    
//退出
    function logout() {
        $.post(
"comet_broadcast.asyn", { action: 'logout', uid: $("#txtLoginID").val() },
        
function(data, status) { _logined = false; alert(data); }
         );
    }

    
//消息等待,接收到消息后显示,发起下一次的消息等待
    function wait() {
        $.post(
"comet_broadcast.asyn", { action: 'connect', uid: $("#txtLoginID").val() },
           
function(data, status) {
              
// alert('wait' + data);
               var result = $("#divResult");
               result.html(result.html() 
+ "<br/>" +"用户列表:"+ data);

               
//服务器返回消息,再次立连接
               if (_logined) {
                   wait();
               }

           }, 
"html"
           );
    }
    
//附加事件
     $("#btnLogin").click(function() { if ($("#txtLoginID").val() == '') alert(''); login(); });
    $(
"#btnLogout").click(function() { logout(); });

});
服务端代码:
public class WebIMAsyncHandler : IHttpAsyncHandler

    {
        
#region IHttpAsyncHandler 成员

        
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            
string _UID = context.Request.Params["uid"];

            WebIMClientAsyncResult _AsyncResult 
= new WebIMClientAsyncResult(context, cb, extraData);

            
string _Content = context.Request.Params["content"];
            
string _Action = context.Request.Params["action"];
            
if (_Action == "login")
            {
                _UID 
= context.Request.Params["uid"];
                _AsyncResult.LoginID 
= _UID;
                WebIMMessageHandler.Instance().Login(_UID, _AsyncResult);
            }
            
else if (_Action == "logout")
            {
                _AsyncResult.LoginID 
= _UID;
                WebIMMessageHandler.Instance().Logout(_UID, _AsyncResult);
            }
            
else if (_Action == "connect")
            {
                _AsyncResult.LoginID 
= _UID;
                WebIMMessageHandler.Instance().Connect(_AsyncResult);
            }
            
else if (_Action == "getuserlist")
            {
                _AsyncResult.LoginID 
= _UID;
                WebIMMessageHandler.Instance().GetUserList(_AsyncResult);
            }


            
//调用
            WebIMMessageHandler.Instance().AddMessage(_Content, _AsyncResult);
            
return _AsyncResult;
        }

        
public void EndProcessRequest(IAsyncResult result)
        {

        }

        
#endregion

        
#region IHttpHandler 成员

        
public bool IsReusable
        {
            
get { return false; ; }
        }

        
public void ProcessRequest(HttpContext context)
        {
            
throw new NotImplementedException();
        }

        
#endregion
    }

    
public class WebIMClientAsyncResult : IAsyncResult
    {

        
bool m_IsCompleted = false;
        
private HttpContext m_Context;
        
private AsyncCallback m_Callback;
        
private object m_ExtraData;
        
private string m_Content;
        
private string m_LoginID = string.Empty;


        
public WebIMClientAsyncResult(HttpContext p_Context, AsyncCallback p_Callback, object p_ExtraData)
        {
            
this.m_Context = p_Context;
            
this.m_Callback = p_Callback;
            
this.m_ExtraData = p_ExtraData;
        }
        
/// <summary>
        
/// 用户编号
        
/// </summary>
        public string LoginID
        {
            
get
            {
                
return m_LoginID;
            }
            
set
            {
                m_LoginID 
= value;
            }
        }
        
/// <summary>
        
/// 发送消息的内容,暂时未使用到
        
/// </summary>
        public string Content
        {
            
get
            {
                
return m_Content;
            }
            
set
            {
                m_Content 
= value;
            }
        }
        
#region IAsyncResult 成员

        
public object AsyncState
        {
            
get { return null; }
        }

        
public WaitHandle AsyncWaitHandle
        {
            
get { return null; }
        }

        
public bool CompletedSynchronously
        {
            
get { return false; }
        }

        
public bool IsCompleted
        {
            
get { return m_IsCompleted; }
        }

        
#endregion

        
/// <summary>
        
/// 向客户端响应消息
        
/// </summary>
        
/// <param name="data"></param>
        public void Send(object data)
        {
            
try
            {
                m_Context.Response.Write(
this.Content);
                
if (m_Callback != null)
                {
                    m_Callback(
this);
                }
                
            }
            
catch { }
            
finally 
            {
                m_IsCompleted 
= true
            }
        }
    }

    
public class WebIMMessageHandler
    {
        
private static readonly WebIMMessageHandler m_Instance = new WebIMMessageHandler();
        
//记录所有请求的客户端
         List<WebIMClientAsyncResult> m_Clients = new List<WebIMClientAsyncResult>();
        
string m_Users = string.Empty;
        
public WebIMMessageHandler()
        {

        }

        
public static WebIMMessageHandler Instance()
        {
            
return m_Instance;
        }

        
/// <summary>
        
/// 登录
        
/// </summary>
        
/// <param name="p_LoginID"></param>
        
/// <param name="p_ClientAsyncResult"></param>
        public void Login(string p_LoginID, WebIMClientAsyncResult p_ClientAsyncResult)
        {
            
bool _Logined = false;
            
foreach (WebIMClientAsyncResult _Item in m_Clients)
            {
                
if (_Item.LoginID == p_LoginID)
                {
                    p_ClientAsyncResult.Content 
= "你已登录";
                    _Logined 
= true;
                    
break;
                }
            }
            
if (!_Logined)
            {
                
//m_Clients.Add(p_ClientAsyncResult);
                p_ClientAsyncResult.Content = "OK";
            }
            p_ClientAsyncResult.Send(
null);


        }

        
private string GetUsers()
        {
            
string _Users = string.Empty;
            
foreach (WebIMClientAsyncResult _Item in m_Clients)
            {
                _Users 
+= _Item.LoginID + ",";
            }
            
return _Users;
        }

        
public void Logout(string p_LoginID, WebIMClientAsyncResult p_ClientAsyncResult)
        {
            
foreach (WebIMClientAsyncResult _Item in m_Clients)
            {
                
if (_Item.LoginID == p_LoginID)
                {
                    m_Clients.Remove(_Item);
                    
break;
                }
            }
            p_ClientAsyncResult.Content 
= "退出成功";
            p_ClientAsyncResult.Send(
null);
            
//UpdateUserList();

            
string _Users = GetUsers();
            
foreach (WebIMClientAsyncResult _Item in m_Clients)
            {
                _Item.Content 
= _Users;
                _Item.Send(
null);
            }
            m_Clients.Clear();
        }

        
public void GetUserList(WebIMClientAsyncResult p_ClientAsyncResult)
        {
            Connect(p_ClientAsyncResult);
            
string _Users = GetUsers();
            
foreach (WebIMClientAsyncResult _Item in m_Clients)
            {
                _Item.Content 
= _Users;
                _Item.Send(
null);
            }
            m_Clients.Clear();
        }

        
public void Connect(WebIMClientAsyncResult p_Client)
        {
            
bool _Exists = false;
            
foreach (WebIMClientAsyncResult _Item in m_Clients)
            {
                
if (_Item.LoginID == p_Client.LoginID)
                {
                    _Exists 
= true;
                    
break;
                }
            }
            
if (!_Exists)
            {
                m_Clients.Add(p_Client);
            }
        }

        
public void UpdateUserList()
        {
            
string _Users = GetUsers();
            
foreach (WebIMClientAsyncResult result in m_Clients)
            {
                result.Content 
= m_Users;
                result.Send(
null);
            }
            m_Clients.Clear();

        }

        
/// <summary>
        
/// 广播消息
        
/// </summary>
        
/// <param name="p_Message"></param>
        
/// <param name="p_AsyncResult"></param>
        public void AddMessage(string p_Message, WebIMClientAsyncResult p_ClientAsyncResult)
        {
            
////保持联连
            //if (p_Message == "-1")
            
//{
            
//    m_Clients.Add(p_ClientAsyncResult);

            
//}
            
//else
            
//{
            
//    //将当前请求的内容输出到客户端
            
//    p_ClientAsyncResult.Content = p_Message;
            
//    p_ClientAsyncResult.Send(null);

            
//    //否则将遍历所有已缓存的client,并将当前内容输出到客户端
            
//    foreach (WebIMClientAsyncResult result in m_Clients)
            
//    {
            
//        result.Content = p_Message;
            
//        result.Send(null);
            
//    }

            
//    //清空所有缓存
            
//    m_Clients.Clear();
            
//}
        }

    }


添加配置文件信息:
        <httpHandlers>
            
<add path="comet_broadcast.asyn" type="CometSample.WebIMAsyncHandler" verb="POST,GET"/>
        
</httpHandlers>


源码下载:CometSample.rar 下节将实现信息的发送与接收;