Wiki定義的聊天室
網絡聊天室通常直稱聊天室,是一種人們可以在線交談的的網絡論壇,在 同一聊天室的人們通過廣播消息進行實時交談。
聊天室可以建立在即時通訊軟件(如MSN Messenger、QQ)、P2P軟件、萬維網(如 Halapo, Meebo ) 等基礎上,萬維網方式更為普通和種類繁多 ,交談的手段不局限於文本,更包括語音、視頻。通常聊天室是按照房間或頻道為單位的,在同一房間 或頻道的網人可以實時地廣播和閱讀公開消息。一般情況下,與其它網絡論壇、即時通訊不同的是,聊 天室不保存聊天記錄。
聊天室的基礎功能定義
用戶能夠通過某種 形式連接到服務, 發送自己的信息給同樣使用該服務的多人看到,並且看到同樣使用該服務的別人發送 的信息。
聊天室的行為
一般的聊天室行為分為兩種
“推” 和 “拉”
推聊天室
推聊天室的行為接近一個中轉點,或者說是一個廣播站。
這種 聊天室簡單明確。
由於根本不需要保存信息 不會存在多個線程訪問的臨界數據,不會涉及到鎖 也就不會產生相應的性能損耗。
缺點也顯而易見,它僅僅支持服務器可以直接向客戶端推送的連 接(比如tcp, udp) ,http這種無連接的協議無法使用。如果是臨時掉線,那麼在重連前的所有數據也 都全都接收不到。
變形品種 點對點聊天室
服務器把推送的義務 轉交給客戶端。
這種方式對用戶發送的內容控制力為0,如果不是tencent這種大牛 在偉大的社 會主義初級階段的和諧社會裡 你執還意作這類點對點聊天室,建議請個好律師
另一種聊天室是
拉聊天室
大多數基於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
class ChatRoom
{
System.Collections.Queue MessageQ=new System.Collections.Queue() ;
void Say(Object message)
{
MessageQ.Enqueue(message);
}
IEnumerable ListenBy(Object user)
{
lock (MessageQ.SyncRoot )
{
foreach (var o in MessageQ)
{
if (o.toUser == user | o.date > DateTime.Now.AddMinutes (-1) )
yield return o;
}
}
}
卻暗含殺機-〉在 enqueue的時候如果queue 空間不足, 自擴張的過程是會影響枚舉的
如何高性能實現"拉聊天室"而盡量做到無鎖高並發?這就是下篇要討論的。
“我拿什麼來實現你 我的接口?”
Code Snippet
namespace WayneGameSolution.Chat
{
using System;
using System.Collections.Generic;
using WayneGameSolution.Membership;
using System.ServiceModel;
[ServiceContract]
public interface IChatChannel
{
/// <summary>
/// 清所有信息
/// </summary>
void Clear ();
/// <summary>
/// 清所有u-28729 ?期信息
/// </summary>
void ClearTimeouted();
/// <summary>
/// 得到用戶所有未u-29701 ?信息
/// </summary>
/// <param name="user">查信息的用戶</param>
/// <returns>所有未u-29701 ?的信息</returns>
///
[OperationContract]
IEnumerable<IChatMessage> GetUserMessage(string user);
/// <summary>
/// 收到信息
/// </summary>
/// <param name="message">發u-28671 ?的消息</param>
///
[OperationContract]
void ReceiveMessage(IChatMessage message);
/// <summary>
/// u-26479 ?u- 28589 ?ID
/// </summary>
///
string ID { get; }
IDictionary<string,DateTime > LastReceivedTime { get; }
LinkedList<IChatMessage> MessageLinkList { get; }
string Name { get; }
int TimeoutSecond { get; set; }
ChannelType Type { get; }
}
public enum ChannelType
{
PublicChannel,
AreaChannel,
GuildChannel,
TemporyChannel,
TeamChannel
}
}