[C#]游戏大厅 从基础开始(5)--绕回来细说聊天室(上)

距离上次写大厅已经有几个月。中间工作繁忙,待学习的东西又很多,又有很多新产品的想法想实践,一直把这个坑闲置着。

直到前两天简单的树遍历枚举器-挑战一个程序员到底能多懒 装配脑袋的几个回帖给我带来一些灵感,让我又重新看看我聊天频道的实现,发现竟然有很多可以推敲重新处理的地方。

昨天上班的时候又把聊天部分整理了下,愿和大家分享。

 

 

 

 

Wiki定义的聊天室

网络聊天室通常直称聊天室,是一种人们可以在线交谈的的网络论坛,在同一聊天室的人们通过广播消息进行实时交谈。

聊天室可以建立在即时通讯软件(如MSN MessengerQQ)、P2P软件、万维网(如 Halapo, Meebo ) 等基础上,万维网方式更为普通和种类繁多,交谈的手段不局限于文本,更包括语音、视频。通常聊天室是按照房间或频道为单位的,在同一房间或频道的网人可以实时地广播和阅读公开消息。一般情况下,与其它网络论坛即时通讯不同的是,聊天室不保存聊天记录。

 

 

 

 

聊天室的基础功能定义

ChatBasic 

用户能够通过某种形式连接到服务, 发送自己的信息给同样使用该服务的多人看到,并且看到同样使用该服务的别人发送的信息。

 

 

 

 

 

聊天室的行为

一般的聊天室行为分为两种

“推” 和 “拉”

 

推聊天室

推聊天室的行为接近一个中转点,或者说是一个广播站。

ChatPush

这种聊天室简单明确。

由于根本不需要保存信息 不会存在多个线程访问的临界数据,不会涉及到锁 也就不会产生相应的性能损耗。

缺点也显而易见,它仅仅支持服务器可以直接向客户端推送的连接(比如tcp, udp) ,http这种无连接的协议无法使用。如果是临时掉线,那么在重连前的所有数据也都全都接收不到。

 

 

变形品种 点对点聊天室

ChatP2P

服务器把推送的义务转交给客户端。

这种方式对用户发送的内容控制力为0,如果不是tencent这种大牛 在伟大的社会主义初级阶段的和谐社会里 你执还意作这类点对点聊天室,建议请个好律师

 

 

另一种聊天室是

拉聊天室

ChatPull

 

大多数基于http的聊天室都是基于这种模式变形。

好处:支持无连接  支持无缝断线重连

坏处:具有公共数据 可能会引发并发冲突  可能会因为锁而降低性能。

 

参考下神奇的asp3年代我们怎么写聊天室:

 

 

1 <%@  language="VBScript" %>
2 <%
3 Response.Buffer=true ' 设 置 输 出 缓 存,用 于 显 示 不 同 页 面。
4 On error resume next ' 忽 略 程 序 出 错 部 分
5 If Request.ServerVariables("Request_Method")="GET" then
6 ' 判 断 客 户 是 以 什 么 方 式 请 求 WEB 页 面
7 '————————
8 ' 客 户 登 陆 界 面
9 '————————
10 %>
11 <form method="POST" action="http://www.cs02.com/luo40.asp">
12 <p>
13     <input type="text" name="nick" size="20" value="nick" style="background-color: rgb(192,192,192)"><br>
14     <input type="submit" value=" 进 入 聊 天 室 " name="B1" style="color: rgb(255,255,0);
15         font-size: 9pt; background-color: rgb(0,128,128)">
16     <p>
17         <input type="hidden" name="log" size="20" value="1"><br>
18     </p>
19 </form>
20 <%
21 Response.End ' 结 束 程 序 的 处 理
22 Else
23 Response.clear ' 清 空 缓 存 中 的 内 容
24 dim talk
25 If Request.Form("nick")<>"" then
26 ' 判 断 客 户 是 是 否 在 聊 天 界 面 中
27 Session("nick")=Request.Form("nick")
28 End If
29 '————————
30 '客 户 聊 天 界 面
31 '————————
32 %>
33 <form method="POST" action="http://www.cs02.com/luo40.asp" name="form1">
34 <p>
35     <%=Session("nick")%>
36     说 话:<input type="text" name="talk" size="50"><br>
37     <input type="submit" value=" 提 交 " name="B1">
38     <input type="reset" value=" 取 消 " name="B2"></p>
39 </form>
40 <a href="http://www.cs02.com/luo40.asp">离 开 </a>
41 <br>
42 <br>
43 <%
44     If Request.Form("log")<>1 then
45         If trim(Request.Form("talk"))="" then
46             ' 判 断 用 户 是 否 没 有 输 入 任 何 内 容
47             talk=Session("nick")&" 沉 默 是 金。"
48         Else
49             talk=trim(Request.Form("talk"))
50             ' 去 掉 字 符 后 的 空 格
51         End If
52 
53     Application.lock
54         Application("show5")=Application("show4")
55         Application("show4")=Application("show3")
56         Application("show3")=Application("show2")
57         Application("show2")=Application("show")
58         Application("show")="<table border='0' cellpadding='0' cellspacing='0' width='85%'><tr><td width='100%' bgcolor='#C0C0C0'></td></tr><tr><td width='100%'><font color='#0000FF'> 来 自 "&Request.ServerVariables("remote_addr")&""&Session("nick")&time&" 说:</font>"&talk&"</td></tr><tr><td width='100%' bgcolor='#C0C0C0'></td></tr></table><br>"
59     Application.UnLock
60     Response.Write Application("show5")
61     Response.Write Application("show4")
62     Response.Write Application("show3")
63     Response.Write Application("show2")
64     Response.Write Application("show")
65     End If
66 End If
67 %>
68 

 

 

 

 

我们看到了锁、原始社会的数据结构,暴力的队列实现,代码云,宗教,神秘主义与性。(女王怀孕了!谁干的?)

 

.net实现的看上去似乎很安全的代码

Code Snippet
  1.  
  2.         class ChatRoom
  3.         {
  4.             System.Collections.Queue MessageQ=new System.Collections.Queue() ;
  5.  
  6.             void Say(Object message)
  7.             {
  8.                 MessageQ.Enqueue(message);
  9.             }
  10.  
  11.             IEnumerable  ListenBy(Object user)
  12.             {
  13.                 lock (MessageQ.SyncRoot )
  14.                 {
  15.                          foreach (var o in MessageQ)
  16.                         {
  17.                             if (o.toUser == user | o.date > DateTime.Now.AddMinutes (-1) )
  18.                                 yield return o;
  19.                         
  20.                         }
  21.                         
  22.                 }
  23.             
  24.             }
  25.  
  26.         \

却暗含杀机-〉在 enqueue的时候如果queue 空间不足, 自扩张的过程是会影响枚举的

 

 

如何高性能实现"拉聊天室"而尽量做到无锁高并发?这就是下篇要讨论的。

 

 

“我拿什么来实现你 我的接口?”

 

Code Snippet
  1. namespace WayneGameSolution.Chat
  2. {
  3.     using System;
  4.     using System.Collections.Generic;
  5.     using WayneGameSolution.Membership;
  6.     using System.ServiceModel;
  7.     [ServiceContract]
  8.     public interface IChatChannel
  9.     {
  10.         /// <summary>
  11.         /// 清所有信息
  12.         /// </summary>
  13.         void Clear();
  14.         /// <summary>
  15.         /// 清所有\u-28729 ?期信息
  16.         /// </summary>
  17.         void ClearTimeouted();
  18.         /// <summary>
  19.         /// 得到用户所有未\u-29701 ?信息
  20.         /// </summary>
  21.         /// <param name="user">查信息的用户</param>
  22.         /// <returns>所有未\u-29701 ?的信息</returns>
  23.         ///
  24.         [OperationContract]
  25.         IEnumerable<IChatMessage> GetUserMessage(string user);
  26.         /// <summary>
  27.         /// 收到信息
  28.         /// </summary>
  29.         /// <param name="message">发\u-28671 ?的消息</param>
  30.         ///
  31.         [OperationContract]
  32.         void ReceiveMessage(IChatMessage message);
  33.         /// <summary>
  34.         /// \u-26479 ?\u-28589 ?ID
  35.         /// </summary>
  36.         ///
  37.  
  38.         string ID { get; }
  39.  
  40.         IDictionary<string,DateTime > LastReceivedTime { get; }
  41.  
  42.         LinkedList<IChatMessage> MessageLinkList { get; }
  43.  
  44.         string Name { get; }
  45.  
  46.         int TimeoutSecond { get; set; }
  47.  
  48.         ChannelType Type { get; }
  49.  
  50.   
  51.     }
  52.  
  53.     public enum ChannelType
  54.     {
  55.         PublicChannel,
  56.         AreaChannel,
  57.         GuildChannel,
  58.         TemporyChannel,
  59.         TeamChannel
  60.     }
  61. }
  62. namespace WayneGameSolution.Chat
  63. {
  64.     using System;
  65.     using System.Collections.Generic;
  66.     using WayneGameSolution.Membership;
  67.     using System.ServiceModel;
  68.     [ServiceContract]
  69.     public interface IChatChannel
  70.     {
  71.         /// <summary>
  72.         /// 清所有信息
  73.         /// </summary>
  74.         void Clear();
  75.         /// <summary>
  76.         /// 清所有\u-28729 ?期信息
  77.         /// </summary>
  78.         void ClearTimeouted();
  79.         /// <summary>
  80.         /// 得到用户所有未\u-29701 ?信息
  81.         /// </summary>
  82.         /// <param name="user">查信息的用户</param>
  83.         /// <returns>所有未\u-29701 ?的信息</returns>
  84.         ///
赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏