線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2467
推到 Plurk!
推到 Facebook!

請問關於聊天室「密頻」的設計方法

答題得分者是:Stallion
remmurds
一般會員


發表:17
回覆:14
積分:16
註冊:2006-10-29

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-06-19 13:53:09 IP:140.130.xxx.xxx 訂閱
目前小弟所構想的設計方法如下: 
1. 宣告一個Structure (或Class)以儲存每位使用者的資料,當有新的使用者連線至伺服器的時候便建立一個Structure並儲存至TList:
<textarea class="cpp" rows="10" cols="60" name="code">struct user { AnsiString UserID; TCustomWinSocket *UserSocket; }; TList *UserList; </textarea>
2. 當某A使用者想要對另一個使用者B發送私人訊息時,便執行以下程式,其中字串Target是在A發送私人訊息給server時便指定的了:
<textarea class="cpp" rows="10" cols="60" name="code">int i; for(i = 0; i < UserList->Count; i ) { if(UserList->Items[i]->UserID == Target) { UserList->Items[i]->Socket->SendText(PrivateMessage); break; } } </textarea> 但是顯然這麼做有個大問題
就是如果當使用者人數很多的時候
這個for迴圈勢必要花費很多時間才能跑完
對效能會有很大的影響
請問各位是否有更良好的解決方案呢?
目前我也只有想到這個方法的說...
------
隨筆網誌: http://reassert.blogspot.com
編輯記錄
remmurds 重新編輯於 2007-06-19 16:34:11, 註解 無‧
Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-06-19 15:57:55 IP:211.22.xxx.xxx 未訂閱
你的狀況我遇過,我的想法是:
1.把所有連線的使用者儲存在一個串列連結的結構體裡面,想要只對單一個使用者發話,勢必要一一比對你想要對話使用者的Socket Handle,才能準確找出發話對象;我認為其實比對的速度並不會慢!即便是1000個使用者又如何?也不會耗費幾個豪秒,問題是你用來儲存連線使用者的結構體以及串列連結的動態記憶體是不是做好了記憶體管理?比如是否有連線上限?或者是當新進來的連線使用者無法動態配置記憶體來儲存連線資訊時該如何回應?
2.如果想要避開逐一比對Socket Handle,可能的作法就像是MSN一樣,Client端除了可以同時跟所有人講話外,另外將目前連線的使用者顯示在清單上面,想要單獨跟誰聊天時,就在清單上面點兩下,另外開啟一個連線對話,也就是說彼此是Client也是Server,這樣也就可以避開Socket Handle比對的程序。
3.請你把本項討論類別改為「問題」
以上請參考~
編輯記錄
Stallion 重新編輯於 2007-06-19 16:15:12, 註解 無‧
remmurds
一般會員


發表:17
回覆:14
積分:16
註冊:2006-10-29

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-06-19 17:03:35 IP:140.130.xxx.xxx 訂閱
感謝您的回答

抱歉我不清楚您所說的「記憶體管理」是指何物?
因為我是交由TList來儲存每一個struct的指標
當某使用者離線之後會將該struct的指標給予delete
也會將TList中對應的Item移除
不曉得這做法是否就是符合您所說的記憶體管理呢?

另外MSN的方法
恐怕在小弟的case中無法使用
但這並不是技術上的問題
而是程式在應用上的限制(這恐怕會是一篇長篇大論了)
不過還是感謝您的意見

另外我想請問諸位的是
如果我所使用的ServerSocket元件是stNonBlocking
那「當for迴圈執行的途中便無法接受其他連線所傳送的資料」的風險應該是存在的
那是否不得不改採用stThreadBlocking了呢?

===================引 用 Stallion 文 章===================
你的狀況我遇過,我的想法是:
1.把所有連線的使用者儲存在一個串列連結的結構體裡面,想要只對單一個使用者發話,勢必要一一比對你想要對話使用者的Socket Handle,才能準確找出發話對象;我認為其實比對的速度並不會慢!即便是1000個使用者又如何?也不會耗費幾個豪秒,問題是你用來儲存連線使用者的結構體以及串列連結的動態記憶體是不是做好了記憶體管理?比如是否有連線上限?或者是當新進來的連線使用者無法動態配置記憶體來儲存連線資訊時該如何回應?
2.如果想要避開逐一比對Socket Handle,可能的作法就像是MSN一樣,Client端除了可以同時跟所有人講話外,另外將目前連線的使用者顯示在清單上面,想要單獨跟誰聊天時,就在清單上面點兩下,另外開啟一個連線對話,也就是說彼此是Client也是Server,這樣也就可以避開Socket Handle比對的程序。
3.請你把本項討論類別改為「問題」
以上請參考~
------
隨筆網誌: http://reassert.blogspot.com
編輯記錄
remmurds 重新編輯於 2007-06-19 17:05:07, 註解 無‧
Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-06-19 17:19:17 IP:211.22.xxx.xxx 未訂閱
抱歉我不清楚您所說的「記憶體管理」是指何物?
因為我是交由TList來儲存每一個struct的指標
當某使用者離線之後會將該struct的指標給予delete
也會將TList中對應的Item移除
不曉得這做法是否就是符合您所說的記憶體管理呢?
是的。

另外MSN的方法
恐怕在小弟的case中無法使用
但這並不是技術上的問題
而是程式在應用上的限制(這恐怕會是一篇長篇大論了)
不過還是感謝您的意見
Client端應該也維護一份上線清單,不然怎麼知道誰在線上?如此,很容易知道每個Client的IP,彼此單獨對話的功能不難實作,只是真的有點繁雜,等於要寫兩套聊天系統,軟體程式真的不好賺!

另外我想請問諸位的是
如果我所使用的ServerSocket元件是stNonBlocking
那「當for迴圈執行的途中便無法接受其他連線所傳送的資料」的風險應該是存在的
那是否不得不改採用stThreadBlocking了呢?
我都是採用Blocking模式,這樣比較好寫不易漏失訊息。
暗黑破壞神
版主


發表:9
回覆:2301
積分:1627
註冊:2004-10-04

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-06-19 18:03:49 IP:61.225.xxx.xxx 未訂閱
還好吧。你這個根本不是問題的問題。
以我改過 ircd 的經驗。
每一個連進來的 client 都會有一個結構來記錄。
而這個結構中,也相對的把這個 socket handle 也記在裏面了。
這樣,當你比對到是 /priv user message 時。
可以直接對那個 user 的 socket handle send message.
這不會花多少時間的。
他們的做法是自己做 Link List
而你用 TList 是相同的,只是 TList 的效率你得自己去評估了。

至於你說要用 thread 的方式?我是跟你說大可不必。
你實作後再來看為什麼。先跟你說,你不見得會懂。

當然你可以先去看過人家 ircd 是怎麼做的。
可以去仿他們的做法。
remmurds
一般會員


發表:17
回覆:14
積分:16
註冊:2006-10-29

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-06-19 18:42:00 IP:140.130.xxx.xxx 訂閱
呃...抱歉...
小弟會想用結構的原因就是以前參考過IRCD的做法
不然如果要我憑空就想到這樣的idea
我想我應該是辦不到的Orz

另外敢問小弟是哪裡做得不對
讓您必須以"你不見得會懂"來給予指責....orz

===================引 用 暗黑破壞神 文 章===================
還好吧。你這個根本不是問題的問題。
以我改過 ircd 的經驗。
每一個連進來的 client 都會有一個結構來記錄。
而這個結構中,也相對的把這個 socket handle 也記在裏面了。
這樣,當你比對到是 /priv user message 時。
可以直接對那個 user 的 socket handle send message.
這不會花多少時間的。
他們的做法是自己做 Link List
而你用 TList 是相同的,只是 TList 的效率你得自己去評估了。

至於你說要用 thread 的方式?我是跟你說大可不必。
你實作後再來看為什麼。先跟你說,你不見得會懂。

當然你可以先去看過人家 ircd 是怎麼做的。
可以去仿他們的做法。
------
隨筆網誌: http://reassert.blogspot.com
暗黑破壞神
版主


發表:9
回覆:2301
積分:1627
註冊:2004-10-04

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-06-19 19:21:46 IP:61.225.xxx.xxx 未訂閱
嗯。那你想想。當你用了  thread 的方式時,你怎麼由這個 socket connect 傳到另一個 socket connect?
這之間又該做那些動作?如何去做”交換”。
然後,所有的連線進來就是一個 thread ,同樣的,你怕資料流失所以你搞這個方式,
但是你有沒有想過這樣的 link list 必須要由這些個 CLIENTS 來”共同維謢”。
這個”共同維謢”的機制,你又要怎麼處理?會不會更耗時?
這就是我說的你不見得會去懂這個部份的”麻煩”
所以 ircd 會那樣做。
而你的結構做法會參考到人家的做法。基本上已經相去不遠。
唯一我會懷疑的就只在 TList 的效率跟人家用 Link List 的不同罷了。
你可以自己寫一段程式去驗證現成 TList 的效率跟自己寫的有什麼差別。

再來你說你看過IRCD的做法。同樣的 IRCD 也會有所謂的 channel list 跟 user list 這兩個
list, 不見得直接去查 user list 會是最快的。
有時由 channel list 先查 user 會比較快找到 user 的 socket handle。
當然這個動作是不保證的。

而你所提到的由 client 去保有其他 user 的 socket handle?
我認為這個倒是不必,這樣反而增加你維護的成本。
在過去。這樣的做法。在於你這樣做可以直接丟一個 socket connect 去另一個 client.
也就是說用 DCC 的做法。不過現在大家在防火牆內的機率都很大。它的實用性就有待考量。

remmurds
一般會員


發表:17
回覆:14
積分:16
註冊:2006-10-29

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-06-19 19:57:39 IP:140.130.xxx.xxx 訂閱
呃...我想您誤會了
"client 去保有其他 user 的 socket handle" 應該是Stallion所提供的意見....0.0"
我並沒有這麼說
礙於程式的應用限制我也沒有這麼做

至於您所提到的Channel List部分
在我目前的case中並沒有Channel List的需求
所以都只是以User List為主

另外您所提到Thread的問題
其實我一開始在評估採用TThreadBlocking時就遇到了這種瓶頸
只好暫時改用NonBlocking來做
當時我只是覺得是因為自己能力不足才會有這種問題
只是來這發問後才知道前輩也是使用NonBlocking的方式來做

至於會這樣問您
純粹只是因為您的語氣讓小弟覺得哪裡有錯而已...

===================引 用 暗黑破壞神 文 章===================
嗯。那你想想。當你用了 thread 的方式時,你怎麼由這個 socket connect 傳到另一個 socket connect?
這之間又該做那些動作?如何去做”交換”。
然後,所有的連線進來就是一個 thread ,同樣的,你怕資料流失所以你搞這個方式,
但是你有沒有想過這樣的 link list 必須要由這些個 CLIENTS 來”共同維謢”。
這個”共同維謢”的機制,你又要怎麼處理?會不會更耗時?
這就是我說的你不見得會去懂這個部份的”麻煩”
所以 ircd 會那樣做。
而你的結構做法會參考到人家的做法。基本上已經相去不遠。
唯一我會懷疑的就只在 TList 的效率跟人家用 Link List 的不同罷了。
你可以自己寫一段程式去驗證現成 TList 的效率跟自己寫的有什麼差別。

再來你說你看過IRCD的做法。同樣的 IRCD 也會有所謂的 channel list 跟 user list 這兩個
list, 不見得直接去查 user list 會是最快的。
有時由 channel list 先查 user 會比較快找到 user 的 socket handle。
當然這個動作是不保證的。

而你所提到的由 client 去保有其他 user 的 socket handle?
我認為這個倒是不必,這樣反而增加你維護的成本。
在過去。這樣的做法。在於你這樣做可以直接丟一個 socket connect 去另一個 client.
也就是說用 DCC 的做法。不過現在大家在防火牆內的機率都很大。它的實用性就有待考量。

------
隨筆網誌: http://reassert.blogspot.com
暗黑破壞神
版主


發表:9
回覆:2301
積分:1627
註冊:2004-10-04

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-06-19 20:27:21 IP:61.225.xxx.xxx 未訂閱
當然,如果你的思考層面還沒有到 thread 會遇到的這一堆問題。
我說了那麼一長串。你不見得會懂。
那我就會等你去實做後,遇到問題後,再來跟你說那部份的問題。
這樣你會比較了解我說的內容。
否則,我說歸說,你又聽不懂,我說了有什麼用?
實做過後來談比較能談出個結論。
Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-06-19 20:30:44 IP:211.22.xxx.xxx 未訂閱
冤枉啊!大人~
1.的確我之前有建議Client端可以保有連線者的資訊,但這樣的作法是為了省去如果Client端邀彼此單獨交談時,可以省去問Server所要交談的Client端資訊,當然!如果要寫一個純聊天室,不具單獨聊天功能的程式我不會這樣做,我會採用前者,就是一一比對Socket Handle。
2.聊天室我的經驗都是採用NoneBlocking的方式來作,因為狀況簡單比較容易掌握;而從暗黑大前面的意見,我看不出來暗黑大鼓勵使用ThreadBlocking的方式來作,相信我,因為很難寫!
===================引 用 remmurds 文 章===================
呃...我想您誤會了
"client 去保有其他 user 的 socket handle" 應該是Stallion所提供的意見....0.0"
我並沒有這麼說
礙於程式的應用限制我也沒有這麼做

至於您所提到的Channel List部分
在我目前的case中並沒有Channel List的需求
所以都只是以User List為主

另外您所提到Thread的問題
其實我一開始在評估採用TThreadBlocking時就遇到了這種瓶頸
只好暫時改用NonBlocking來做
當時我只是覺得是因為自己能力不足才會有這種問題
只是來這發問後才知道前輩也是使用NonBlocking的方式來做

至於會這樣問您
純粹只是因為您的語氣讓小弟覺得哪裡有錯而已...
編輯記錄
Stallion 重新編輯於 2007-06-20 18:49:29, 註解 對不起打錯字!‧
Stallion 重新編輯於 2007-06-20 19:54:28, 註解 無‧
remmurds
一般會員


發表:17
回覆:14
積分:16
註冊:2006-10-29

發送簡訊給我
#11 引用回覆 回覆 發表時間:2007-06-19 20:47:44 IP:140.130.xxx.xxx 訂閱
哈哈
因為TServerSocket元件就只有ThreadBlocking和NonBlocking兩種可以選而已
抱歉我誤會您的意思了

===================引 用 Stallion 文 章===================

2.聊天室我的經驗都是採用Blocking的方式來作,因為狀況簡單比較容易掌握;而從暗黑大前面的意見,我看不出來暗黑大鼓勵使用NoneBlocking的方式來作,相信我,因為很難寫!
------
隨筆網誌: http://reassert.blogspot.com
暗黑破壞神
版主


發表:9
回覆:2301
積分:1627
註冊:2004-10-04

發送簡訊給我
#12 引用回覆 回覆 發表時間:2007-06-20 19:46:55 IP:220.131.xxx.xxx 未訂閱
你可以用 nonblocking 呀。
因為每個命令列都會有 "\n" 的存在。
你可以利用它來做”結束”判斷。

而每一個 connect 進來的 client 都會一直把目前收到的字,丟到各個 client 的資料結構中的一個記憶體,EX cmd_buffer.
直到判斷收到的為 "\n" 才做整體動作。
這遠比你用 thread 簡單多了。
而且比 blocking 會流失資料的處理方式還要安全。

===================引 用 remmurds 文 章===================
哈哈
因為TServerSocket元件就只有ThreadBlocking和NonBlocking兩種可以選而已
抱歉我誤會您的意思了

===================引 用 Stallion 文 章===================

2.聊天室我的經驗都是採用Blocking的方式來作,因為狀況簡單比較容易掌握;而從暗黑大前面的意見,我看不出來暗黑大鼓勵使用NoneBlocking的方式來作,相信我,因為很難寫!
系統時間:2024-03-29 16:58:55
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!