WebIM系列文章

之前笔者发布的云翔在线软件平台中已经包含了一个功能相对比较齐全的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.基本思路

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

接收消息的流程:

发送消息流程:

发送消息和添加监听器将由一个类型为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;}
}

3.客户端接收消息

客户端接收消息并不复杂,只需要发送请求,返回后在发送另一个请求即可,代码如下:

function Receive()
{var data = {Receiver: User,Sender: Peer,From: m_From};function Receive_Error(ex){alert(ex);m_ErrorCount++;if (m_ErrorCount < 5){//发送下一个请求setTimeout(Receive, 1000);}}function Receive_Callback(xml, text){m_ErrorCount = 0;//将JSON转成数据var ret = System.ParseJson(text);//显示消息for (var i in ret.Messages){m_MsgPanel.AddMessage(ret.Messages[i]);}if (ret.Messages.length > 0){m_From = ret.Messages[ret.Messages.length - 1].CreatedTime;}//发送下一个请求setTimeout(Receive, 50);}System.Post(Receive_Callback, Receive_Error, "recevie.aspx", System.RenderJson(data));
}
WebIM源代码(注意:开发时起始页为WebIM_Dev.htm,直接打开起始页为WebIM.htm)

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

转载于:https://www.cnblogs.com/lucc/archive/2010/04/24/1719397.html

一步一步打造WebIM(1)相关推荐

  1. PVE虚拟服务器配置,我与PVE的交往史 篇一:如何使用虚拟机PVE一步一步打造自己想要的ALL IN ONE 主机...

    我与PVE的交往史 篇一:如何使用虚拟机PVE一步一步打造自己想要的ALL IN ONE 主机 2021-03-15 00:08:12 79点赞 381收藏 33评论 创作立场声明:我是一个折腾的人, ...

  2. WPF+WCF一步一步打造音频聊天室(三):语音聊天

    前一篇文章中实现了文字聊天和共享白板的功能,这篇文章中,我将在前一篇文章的基础上实现语音聊天的功能.语音聊天要比文字聊天和共享白板难度要大一点. 实现的大概的流程为: 1.一个聊天室成员向另外一个成员 ...

  3. WPF+WCF一步一步打造音频聊天室(一):概述

    前几天在老徐的MSN群中聊WCF.我突然想到了用WPF和WCF来打造音频聊天室这么一个轮子.其实是这样的,我在的公司是两岸三地合作开发的.两岸是指大陆和台湾,三地是指深圳.台北.高雄.由于公司很小,所 ...

  4. 一步一步用jenkins,ansible,supervisor打造一个web构建发布系统

    新blog地址:http://hengyunabc.github.io/deploy-system-build-with-jenkins-ansible-supervisor/ 一步一步用jenkin ...

  5. 天龙八步-》打造debian-desktop-》配置桌面[三](转)

    天龙八步->打造debian-desktop->配置桌面[三](转)[@more@] 第三章 配置桌面 1.配置simsun字体到:(以下1和2可建立脚本文件/bat/xconf来作) 建 ...

  6. 天龙八步-》打造debian-desktop-》安装声卡[五](转)

    天龙八步->打造debian-desktop->安装声卡[五](转)[@more@] 第五章 安装声卡(alsa方式) 方法一:apt方法 比如我的声卡为ac97的via8233: 1.a ...

  7. 天龙八步-》打造debian-desktop-》安装桌面和软件[二](转)

    天龙八步->打造debian-desktop->安装桌面和软件[二](转)[@more@] 第二章 安装桌面和软件 1.tasksel与dselect: tasksel: 安装三个东西:X ...

  8. 一步一步教你在 Android 里创建自己的账号系统(一)

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 大家在 ...

  9. 华为p4支持鸿蒙功能吗_吹过的牛都一步一步给实现了!明年华为手机支持升级鸿蒙系统!...

    12月16日,华为举行 HarmonyOS 2.0 手机开发者 Beta 活动,现场正式发布了 HarmonyOS 2.0 手机开发者 Beta 版本.据悉,本次 HarmonyOS 2.0 公测设备 ...

  10. 一步一步SharePoint 2007之五:向网站中添加一个子网站

    一步一步SharePoint 2007之五:向网站中添加一个子网站 摘要 感受完看到成果的激动,感受完邻家女孩的漂亮.可爱和端庄,不要停止,来,让我们一起来动手打造心目中的完美女神吧! 本篇文章将介绍 ...

最新文章

  1. 关于植物和共生微生物,这116张PPT讲明白了(值得收藏!)
  2. SQL Server 2008连载之存储结构——基本系统视图
  3. 机器学习算法系列(一)-基础机器学习算法入门
  4. php html 停止工作,换行符php和html无法正常工作
  5. 语义分割系列5-Pspnet(pytorch实现)
  6. SQL注入:SQL注入防御
  7. Unity 高级程序员应该具备怎样的能力?要怎样成长为 Unity 高级程序员?
  8. 错误:Mixed Content: The page at ‘https://XXX’ was loaded over HTTPS, but requested an insecure.......
  9. 【java基础】同比和环比
  10. 解答诸葛亮反思的七条内容
  11. java8 协程_Java8 异步编程—CompletableFuture
  12. HDLBits 系列(8)——Sequential Logic(Finite State Machines(一))
  13. 团队作业五之旅游行业手机APP分析
  14. 区块链:分布式系统核心技术
  15. 参考 | Windows安装cython-bbox
  16. 【Python深度学习之路】-3.1性能评价指标
  17. 用DIV+CSS技术设计的鲜花网站(web前端网页制作课作业)
  18. helpinst.exe
  19. 格灵深瞳:人脸识别工业级大规模人脸识别实践探讨 | 百万人学AI
  20. 计算机专业英语首字母缩略词,计算机专业英语缩略词计算机专业英语缩略词.doc...

热门文章

  1. 计算机休眠设置电源开关,电脑入门(五)、开关机操作
  2. CAD .net开发-从注册表中获取CAD安装路径
  3. 浪潮NF5270 M4 无法识别大容量硬盘问题及处理办法
  4. 计算机培训开班仪式主持词,公文写作培训班主持词
  5. 机械原理第二章 连杆机构总结
  6. 软件设计师笔记----计算机组成与结构
  7. 基于UMAT的低密度泡沫本构实现
  8. ubuntu快捷键设置后 无效问题
  9. 习题8-2 在数组中查找指定元素 (15 分)(python)
  10. 关于Oracle-HR表的查询