`
lucc
  • 浏览: 10896 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

一步一步打造WebIM(1)

阅读更多

之前笔者发布的云翔在线软件平台中已经包含了一个功能相对比较齐全的WebIM,这个系列的文章就是介绍如何开发出功能类似的WebIM,在文章开始前,先介绍一下相关的技术:

1.Comet

Comet 是一种新的 Web 应用架构。基于这种架构开发的应用中,服务器端会主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求。Comet 架构非常适合事件驱动的 Web 应用,以及对交互性和实时性要求很强的应用,如股票交易行情分析、聊天室和 Web 版在线游戏等。

在.NET要实现Comet就要用到IHttpAsyncHandler,在开始阅读文章前,建议先了解一下IHttpAsyncHandler

2.Lesktop

Lesktop是一款用于开发RIA网站的开源JS界面库,Lesktop提供了一个功能强大的可视化开发工具帮助您快速的开发RIA网站。这个系列介绍的WebIM的前台UI将使用Lesktop来开发。

 

接下来,将开始今天的主题,开发一个简单的WebIM,这个WebIM将使用Comet技术,从而避免在客户端和服务端轮询,提高WebIM的性能(目前主要实现能够聊天,其他功能会在以后不断完善)。客户端界面在这就不详细介绍了,用Lesktop拖拖控件就可以了,效果如下:

1

1.基本思路

Comet便是指服务器推技术。它的实现方式是在浏览器与服务器之间建立一个长连接,待获得消息之后立即返回。否则持续等待,直至超时。客户端得到消息或超时之后,又会立即建立另一个长连接。Comet技术的最大优势,自然就是很高的即使性。在.NET中实现这种方式并不困难,用IHttpAsyncHandler即可。

接收消息的流程:

clip_image001

发送消息流程:

clip_image001[8]

发送消息和添加监听器将由一个类型为MessageManagement对象来负责,

添加监听器代码如下:

/// <summary>
/// 添加消息监听器,如果查找到符合监听器条件的消息,返回false,此时不会添加监听器
/// 如果没有查找到符合监听器条件的消息,返回true,此时监听器将被添加到m_Listeners中
/// </summary>
public bool AddListener(String receiver, String sender, Nullable<DateTime> from, WebIM_AsyncResult asynResult)
{
    MessageListener listener = new MessageListener(receiver, sender, from, asynResult);
    lock (m_Lock)
    {
        if (!m_Listeners.ContainsKey(receiver))
        {
            m_Listeners.Add(receiver, new List<MessageListener>());
        }
        List<MessageListener> listeners = m_Listeners[receiver] as List<MessageListener>;

        //查找消息
        List<Message> messages = Find(receiver, sender, from);

        if (messages.Count == 0)
        {
            //插入监听器
            listeners.Add(listener);
        }
        else
        {
            //发送消息
            listener.Send(messages);
        }
        return messages.Count == 0;
    }
}

发送消息代码如下:

/// <summary>
/// 插入新的消息,插入消息后将查询m_Listeners中是否有符合条件的监听器,如存在,同时将消息发送出去
/// </summary>
public Message NewMessage(String receiver, String sender, DateTime createdTime, String content)
{
    lock (m_Lock)
    {
        Message message = new Message(sender, receiver, content, createdTime, ++m_MaxKey);

        SQLiteCommand cmd = new SQLiteCommand(
            "insert into Message (Receiver,Sender,Content,CreatedTime,Key) values (?,?,?,?,?)",
            m_Conn
        );
        cmd.Parameters.Add("Receiver", DbType.String).Value = message.Receiver;
        cmd.Parameters.Add("Sender", DbType.String).Value = message.Sender;
        cmd.Parameters.Add("Content", DbType.String).Value = message.Content;
        cmd.Parameters.Add("CreatedTime", DbType.DateTime).Value = message.CreatedTime;
        cmd.Parameters.Add("Key", DbType.Int64).Value = message.Key;

        cmd.ExecuteNonQuery();

        List<Message> messages = new List<Message>();
        messages.Add(message);

        if (m_Listeners.ContainsKey(receiver))
        {
            List<MessageListener> listeners = m_Listeners[receiver] as List<MessageListener>;
            List<MessageListener> removeListeners = new List<MessageListener>();
            foreach (MessageListener listener in listeners)
            {
                if ((listener.Sender == "*" || String.Compare(listener.Sender, sender, true) == 0) && 
                    (listener.From == null || message.CreatedTime > listener.From))
                {
                    listener.Send(messages);
                    removeListeners.Add(listener);

                    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(listener.Complete));
                }
            }

            foreach (MessageListener listener in removeListeners)
            {
                //移除监听器
                listeners.Remove(listener);
            }
        }

        return message;
    }
}

2.使用IHttpAsyncHandler实现Comet

IHttpAsyncHandler的介绍可以查阅下msdn,以下是接收消息的源代码,主要是重写BeginProcessRequest和EndProcessRequest:

public class WebIM_ReceiveHandler : IHttpAsyncHandler
{
    public WebIM_ReceiveHandler()
    {
    }

    HttpContext m_Context = null;

    IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
    {
        m_Context = context;

        System.IO.Stream inputStream = context.Request.InputStream;
        Byte[] buffer = new Byte[inputStream.Length];
        inputStream.Read(buffer, 0, (int)inputStream.Length);
        string content = context.Request.ContentEncoding.GetString(buffer);
        Hashtable data = Utility.ParseJson(content) as Hashtable;

        WebIM_AsyncResult asyncResult = new WebIM_AsyncResult(cb, extraData);
        Nullable<DateTime> from = data.ContainsKey("From") ? new Nullable<DateTime>((DateTime)data["From"]) : null;

        if (!MessageManagement.Instance.AddListener(data["Receiver"] as string, data["Sender"] as string, from, asyncResult))
        {
            //已有消息,发送消息并结束链接
            asyncResult.Complete(null);
        }

        return asyncResult;
    }

    void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
    {
        //将消息发送到客户端
        WebIM_AsyncResult asyncResult = result as WebIM_AsyncResult;
        asyncResult.Send(m_Context);
    }

    void IHttpHandler.ProcessRequest(HttpContext context)
    {
    }

    bool IHttpHandler.IsReusable
    {
        get { return true; }
    }
}

public class WebIM_AsyncResult : IAsyncResult
{
    AsyncCallback m_AsyncCallback = null;
    object m_Data = null;
    bool m_IsCompleted = false;

    public WebIM_AsyncResult(AsyncCallback callback, Object extraData)
    {
        m_Data = extraData;
        m_AsyncCallback = callback;
    }

    bool IAsyncResult.IsCompleted { get { return m_IsCompleted; } }

    bool IAsyncResult.CompletedSynchronously { get { return false; } }

    WaitHandle IAsyncResult.AsyncWaitHandle { get { return null; } }

    Object IAsyncResult.AsyncState { get { return m_Data; } }

    StringBuilder m_Cache = new StringBuilder();

    public void Write(object content)
    {
        m_Cache.Append(content.ToString());
    }

    public void Send(HttpContext context)
    {
        context.Response.Write(m_Cache.ToString());
    }

    public void Complete(object data)
    {
        m_AsyncCallback(this);
        m_IsCompleted = true;
    }
}

 

WebIM源代码(注意:开发时起始页为WebIM_Dev.htm,直接打开起始页为WebIM.htm)

一个简单的WebIM就先介绍到这里,如果您有任何问题,可以通过WebIM与我联系。

 


以下是广告时间,主要介绍云翔在线软件平台的最新动态。此次更新主要修改了平台的操作界面,新的界面将平台所有功能入口放到了网页的上部分,其余版面用于浏览网页,您可以自己设定一个常用的页面作为首页,系统启动后将自动打开您设置的页面。如图所示:

image17

尽管使用了新的界面,原来的桌面模式仍然保留,您可以在登录时切换登录模式:

image

2
2
分享到:
评论

相关推荐

    webim

    1. **WebSocket协议**:WebSocket是HTML5引入的一种在单个TCP连接上进行全双工通信的协议。它允许服务器主动向客户端推送数据,解决了HTTP协议下长轮询、 comet等技术的效率问题,实现了低延迟的实时通信。 2. **...

    WEBIM网站开发用途

    1. **选择或开发后台服务**:根据需求选择合适的WEBIM服务提供商(如Openfire、Easemob等)或者自行开发。 2. **部署WebSocket服务器**:确保服务器支持WebSocket,配置相应的证书和端口。 3. **前端集成**:将...

    WebIM_Ajax框架

    1.引入 runwebim.js 脚本只会损耗很少资源(几乎可以忽略),只有运行 RunWebIM() 启动了 WebIM 才会动态加载样式和脚本; 2.只有登录成功后,WebIM 才会启动心跳包(每隔一段时间ajax请求数据); 3.启动心跳包后,...

    webim,即时通信软件,php

    1. **WebIM架构与原理** WebIM基于WebSocket协议,这是一种在浏览器和服务器之间建立长连接的协议,克服了HTTP协议的限制,实现了双向通信。WebSocket使得服务器能主动推送消息到客户端,从而实现实时通信。WebIM...

    webim(web即时通)学习文档

    1. **WebSocket协议**:WebSocket是HTML5引入的一种在单个TCP连接上进行全双工通信的协议,它使得服务器可以主动向客户端推送数据,解决了传统HTTP请求-响应模式的不足,是实现WebIM的关键技术。 2. **即时通讯架构...

    webim-for-thinkphp

    1. **WebIM**:WebIM通常基于WebSocket协议,能够实现实时双向通信,确保消息的即时传递。WebIM的特点包括轻量级、跨平台、低延迟和高效率,适合在网页中实现聊天功能。此项目中的WebIM可能包括前端界面、后端服务器...

    鱼鱼WEBIM 2008-2010

    鱼鱼WEBIM 2008-2010 aspdll版 要正常运行程序,请注册组件。 作者QQ:260332019 更新: 1、发消息页面、添加应用页面可以复制张贴等 2、增加了修改应用 3、突出鱼鱼应用,欢迎大家开发出鱼鱼的小应用程序。 ...

    Webim for 记事狗插件

    1. 解压安装包获得utf8, gbk两个版本,上传相应版本到记事狗plugin/目录解压 2. 登录JishiGou管理后台安装新插件webim 3. 启用插件 4. 设置插件参数,主要是注册域名和apikey 运行环境 PHP版本5.1+, 记事狗微博版本...

    WebQQ WebIM WebSocket

    1. **WebSocket协议**:WebSocket是一种在客户端和服务器之间建立持久连接的网络协议,允许双方进行全双工通信。相比HTTP,WebSocket更适合需要频繁交互的实时应用,如在线聊天、游戏、股票交易等。它通过握手协议...

    实现webim得用ajax

    WebIM(Web即时通讯)是一种基于网页的即时通信技术,它允许用户在浏览器上进行实时的文本、语音、视频聊天,无需安装额外的客户端软件。实现WebIM的关键技术之一是Ajax(Asynchronous JavaScript and XML),它是一...

    openfire+smack开发webim笔记

    1. Ajax无刷新交互:通过定时器定期拉取数据,逐步优化刷新频率,以减少网络负担。 2. Pushlet技术:允许服务器主动推送数据到客户端,提高实时性。 3. Comet技术:模拟服务器推送,通过长时间连接实现双向通信。 4....

    免费下载WEBIM java pushlet .net php

    1. **WebIM**:WebIM是一种基于Web的即时通讯系统,允许用户在浏览器内进行实时聊天,无需安装额外的客户端软件。它通常依赖于WebSocket等技术来实现双向、低延迟的数据传输。 2. **Java Pushlet**:Pushlet是Java...

    webim实现含src

    WebIM Client简单实现 本文描述了使用javascript直接连接xmpp server的方法和详细配置,使用XEP-0124和xmpp server无缝接合。从而实现webim的实时性和高效性。

    在线聊天WEBIM.rar

    1. **WebSocket协议**:WebSocket是HTML5引入的一种低延迟、双向通信协议,它为Web应用程序提供了持久连接的能力,使得服务器可以主动向客户端推送数据,这对于实时聊天应用至关重要。 2. **JavaScript框架**:...

    webim-for-flask-master

    【标题】"webim-for-flask-master"是一个基于Flask框架构建的实时通讯系统项目,主要专注于实现Web即时通讯(WebIM)功能。这个项目利用Python的Flask库,为Web应用提供了一个轻量级、高效的实时通信解决方案。 ...

    环信WebIM超精简示例

    环信WebIM是一款专为开发者设计的实时通讯解决方案,它提供了丰富的API和SDK,使得在Web应用中集成即时通讯功能变得简单。这个“环信WebIM超精简示例”是为了帮助开发者快速理解和上手环信WebIM服务而提供的一个基础...

    WebIM研究整理

    1.WebIM目录对应http://blog.csdn.net/zwdsmileface/article/details/45111111和http://blog.csdn.net/ibm_hoojo/article/details/7850540 2个帖子集合可以,但是后一篇帖子的jsjac.js版本没找到,希望网友们提供 2....

    在线客服服务支持系统webim163

    1. COPYING:这是一个关于软件许可的信息文件,通常包含了软件的授权协议,比如GPL、MIT等。这意味着WebIM163可能是开源软件,并遵循特定的开源许可证规定,允许用户自由使用、修改和分发源代码。 2. default.css:...

    WebIM-for-近乎SNS插件 v5.3

    WebIM-for-近乎SNS是为近乎SNS微博社区开发的站内即时消息系统,实现近乎SNS微博社区好友间的即时聊天。Nextalk是专为社区网站开发的即时消息系统NexTalk是专为社区网站(论坛/社区/微博)开发的简单,专业,开源的...

Global site tag (gtag.js) - Google Analytics