亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 91013 | 回復(fù): 100
打印 上一主題 下一主題

談?wù)勀憬佑|的通訊程序的模型 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2011-01-01 22:15 |只看該作者 |倒序瀏覽
本帖最后由 duanjigang 于 2011-01-10 16:33 編輯

################2011-01-06
在1,2,4,5,67,22樓對目前涉及到的三種模型或者說程序的實現(xiàn)方法,做了詳盡的描述,歡迎大家積極拍磚,提出改進建議,或者發(fā)起實踐活動來實現(xiàn)這樣的設(shè)計思路,并與我們分享您的經(jīng)驗。

推薦下34樓的做法,個人感覺也很不錯
########################

應(yīng)用程序也做了不少了,特別是在通訊這塊做了好幾年,好幾個項目,來來回回,思想和選擇經(jīng)過了好幾番轉(zhuǎn)變,經(jīng)常會想起一些技術(shù)上的選擇問題,不知道該如何取舍,今晚屋子比較安靜,整理下思緒,發(fā)起這個話題,順便聽聽大家的看法。

   剛開始接觸網(wǎng)絡(luò)編程時,寫的最簡單的通訊程序,就是server-client一對一的模型,可能還不知道有非阻塞和select等概念,只是覺得測試數(shù)據(jù)發(fā)送過去了,接收到了就很高興,當(dāng)面臨多連接,多種消息類型時,就開始頭大了。大概07年初的時候,我當(dāng)時的想法,就跟前不久一個同學(xué)的設(shè)計思路一樣,對于一對多的通訊程序,服務(wù)器監(jiān)聽,接受到一個客戶端請求時,就為該連接創(chuàng)建一個線程,并且把獲取到的連接套接字交給線程去使用,當(dāng)子線程完成通訊或者出錯后,就會關(guān)閉連接套接字,然后退出。這個模型在我當(dāng)時看來很厲害了(應(yīng)該比同學(xué)問那個,給每個新獲取的連接套接字創(chuàng)建一個進程強點吧,呵呵),當(dāng)時這個程序也是在客戶那里跑起來,基本上線了,但是印象里出了不少問題,多線程程序在我印象里更不好調(diào)試。。反正是被這個寫法折騰的夠苦,后來一提到多線程處理多連接,每個線程一個連接的做法,我就頭大。呵呵,不知道有沒有人這樣寫,談?wù)勛约呵擅畹脑O(shè)計或者遇到的問題?
第一種模型,是否可以用以下圖來表示?

論壇徽章:
0
2 [報告]
發(fā)表于 2011-01-01 22:29 |只看該作者
本帖最后由 duanjigang 于 2011-01-02 10:43 編輯

呵呵,早上看看昨天的文字,發(fā)現(xiàn)用詞很土。:wink:
后來看到了第二種寫法,覺得不錯。

客戶端程序分為兩個線程:連接線程和數(shù)據(jù)處理線程。
在提出select和poll或者epoll之前,針對多個連接的通訊,大都使用的非阻塞socket吧。

     先說說連接線程,連接線程和數(shù)據(jù)線程共享一個server列表,或者叫一個server list.這個server列表的每一個節(jié)點,代表了
一個將要連接過去的主機,同時還存儲了該跟主機相關(guān)的信息,最常見的是IP地址,編號,socket描述符,發(fā)送緩沖區(qū),發(fā)送數(shù)據(jù)指針,數(shù)據(jù)總長度等信息。連接線程要做的事情很簡單,遍歷主機列表的每一個節(jié)點,如果發(fā)現(xiàn)某個主機的連接狀態(tài)處于“未連接”狀態(tài),則嘗試連接該主機,當(dāng)然這個連接也是有超時限制的。如果連接成功,存儲該到該主機的連接的socket描述符,修改連接標志位。標明該主機已經(jīng)被連接上,其實也就是通知數(shù)據(jù)處理線程,該主機可以進行通訊了。
      再說數(shù)據(jù)處理線程,數(shù)據(jù)處理線程顧名思義,就是處理數(shù)據(jù)線程,從客戶端的角度來說,數(shù)據(jù)處理線程大多數(shù)情況下是做出發(fā)送數(shù)據(jù)的狀態(tài)。在這個模型中,也是如此,數(shù)據(jù)處理線程也遍歷主機列表,檢查每個主機的連接狀態(tài),如果該主機已經(jīng)連接上,并且發(fā)送緩沖區(qū)有數(shù)據(jù)未發(fā)送出去,則使用非阻塞的方式向該主機發(fā)送數(shù)據(jù),如果發(fā)送失敗,則關(guān)閉socket,并且修改主機的連接狀態(tài)為未連接狀態(tài),以告知連接線程,這個主機已經(jīng)斷開了,你丫需要重新去連接它了。如果發(fā)送成功,則更新發(fā)送緩緩沖區(qū)的數(shù)據(jù)指針,注意,這種發(fā)送沒必要在一個while循環(huán)中一直發(fā)送,直到發(fā)送完成,個人覺得發(fā)送一次就可以了,不過好像也有人嘗試發(fā)送最多三次。個人理解,為了減少在一臺主機上的長時間發(fā)送而造成對其它主機數(shù)據(jù)發(fā)送的延遲影響,還是只發(fā)送一次好。
第二種方式的客戶端程序可以用這個圖來描述下。

論壇徽章:
1
天蝎座
日期:2013-08-25 10:27:22
3 [報告]
發(fā)表于 2011-01-02 01:25 |只看該作者
圖是紅叉叉。。
沒必要1個連接一個線程把。

論壇徽章:
0
4 [報告]
發(fā)表于 2011-01-02 09:01 |只看該作者
圖是紅叉叉。。
沒必要1個連接一個線程把。
yangsf5 發(fā)表于 2011-01-02 01:25



    嗯,是的,呵呵,最初是這么設(shè)計的,而且現(xiàn)在有些剛接觸網(wǎng)絡(luò)通訊類程序的人也會下意識的去這么考慮。
我是想從一開始到現(xiàn)在,把所有遇到過的寫法大致上都總結(jié)下,大家一起討論每種的問題,優(yōu)缺點和性能比較。

論壇徽章:
0
5 [報告]
發(fā)表于 2011-01-02 11:03 |只看該作者
本帖最后由 duanjigang 于 2011-01-02 11:06 編輯

接著來說第二種模型的服務(wù)端程序,對于服務(wù)端程序來說,跟客戶端程序類似,也是兩個線程工作。
      一個連接接收線程,一般來說,都是主線程來負責(zé),創(chuàng)建socket后,bind,listen。。然后在一個死循環(huán)當(dāng)中嘗試accept來自不同主機的連接請求。每收到一個連接請求,就把該連接的IP地址,端口等信息存儲到連接列表當(dāng)中,并且初始化接收緩沖區(qū)等信息。
    另外一個是數(shù)據(jù)接收線程,該線程遍歷連接列表,嘗試從每一個連接讀取數(shù)據(jù),如果讀取失敗,則關(guān)閉連接套接字,釋放該連接節(jié)點。如果接收成功,則檢測是否是一個完整的消息,是的話,則進行處理,不是一個完整的消息,則繼續(xù)緩存,更新接收緩沖區(qū)的指針。
  服務(wù)器端程序相對客戶端程序來說,處理的事務(wù)少點。
服務(wù)端程序的結(jié)構(gòu)和工作流程可以用下圖來表示下:

論壇徽章:
0
6 [報告]
發(fā)表于 2011-01-02 11:39 |只看該作者
第二種雙線程的方式已經(jīng)是一種不錯的模型了,在實際中應(yīng)用也不少,上面量段文字和圖片說明了服務(wù)端和客戶端的基本工作方式和數(shù)據(jù)結(jié)構(gòu)梗概。不過有些細節(jié)還是需要注意并加以處理的:
  我們都知道,服務(wù)端和客戶端都是采用非阻塞方式進行數(shù)據(jù)的發(fā)送和接收的。這樣就有一個特點:對于專注從事于數(shù)據(jù)發(fā)送的客戶端程序來說,如果客戶端到服務(wù)端的網(wǎng)絡(luò)出現(xiàn)中斷,客戶端的發(fā)送操作會出錯,這時,客戶端程序能夠發(fā)現(xiàn)這個故障,并且能夠進行正確的處理(關(guān)閉socket,后面嘗試重新連接)。而對于服務(wù)器端程序來說,因為它遍歷連接列表進行數(shù)據(jù)接收,采用的是非阻塞方式,即使客戶端的連接已經(jīng)斷開,他調(diào)用recv操作,返回的結(jié)果跟沒有收到數(shù)據(jù)是一樣的,都是0(這個結(jié)論我應(yīng)該沒有記錯吧,如果有錯,望指出)。也就是說,服務(wù)端通過只讀取的操作是無法發(fā)現(xiàn)客戶端的斷開狀態(tài)的。從系統(tǒng)資源角度考慮,會造成很多未完全關(guān)閉的連接,另外,從服務(wù)端程序來考慮,也是無法忍受的,比如服務(wù)端采用的連接列表長度為1000,如果有幾十個客戶端斷開連接并且重新連接幾次,這樣在服務(wù)端的連接列表里會增加上百個貌似正常實際上卻是無效的連接節(jié)點,時間再長點,就會導(dǎo)致服務(wù)端列表的溢出,另外,從后面的話題的角度出發(fā),列表過長,會導(dǎo)致接收線程遍歷的節(jié)點次數(shù)增大,浪費過多的CPU時間。

論壇徽章:
0
7 [報告]
發(fā)表于 2011-01-02 11:56 |只看該作者
本帖最后由 duanjigang 于 2011-01-02 19:10 編輯

接著6樓的問題。
  既然只讀取的操作不能發(fā)現(xiàn)連接的斷開,為什么不增加一個發(fā)送操作?是的,這個想法很好,不過我們要明白,這個發(fā)送操作的目的只是為了檢測客戶端連接的狀態(tài)。
  既然服務(wù)端會通過發(fā)送數(shù)據(jù)的方法來檢測客戶端的在線狀態(tài),那么客戶端就不能置之不理,禮尚往來還是有必要的,因為如果客戶端不理會服務(wù)端的發(fā)送數(shù)據(jù)的話,服務(wù)端發(fā)送到客戶端接收緩沖區(qū)的數(shù)據(jù)就不會被讀取,如果不存在超時丟棄或者覆蓋的話,接收緩沖區(qū)總會被寫滿的。因此,客戶端還是需要去讀取服務(wù)端發(fā)送過來的檢驗數(shù)據(jù)的。
   跟據(jù)上面的情形,可以增加這樣一項工作,在服務(wù)器端的主機列表的每個節(jié)點上存儲接收到客戶端數(shù)據(jù)的最新時間,然后定義一個超時時間,如果超過這個時限沒有收到來自某個主機的數(shù)據(jù),則嘗試向該主機發(fā)送一個握手消息,這時就能檢測是否連接已經(jīng)斷開了。
   對于客戶端而言,為每一個服務(wù)器保存一個發(fā)送數(shù)據(jù)的最新時間,如果最后一次發(fā)送數(shù)據(jù)的時間到目前的時間差超過這個時限,則嘗試從服務(wù)端讀取握手消息,這樣就能把服務(wù)器端發(fā)過來的握手消息接收過來,比較理想的解決了上面討論中可能出現(xiàn)的問題。
     這種非阻塞的模型,有些人認為是比較浪費CPU時間的,不過通過一些方法可以適當(dāng)降低CPU使用的,在連接列表不是特別長,并且每個連接都不是特別空閑的情況下,性能還是很不錯的。
后面有時間,我把這種模型的實現(xiàn)整理下,放出來大家可以參考下。

論壇徽章:
36
IT運維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
8 [報告]
發(fā)表于 2011-01-02 17:58 |只看該作者
duan 兄好文章,受益匪淺。

論壇徽章:
0
9 [報告]
發(fā)表于 2011-01-02 18:59 |只看該作者
duan 兄好文章,受益匪淺。
Godbach 發(fā)表于 2011-01-02 17:58



    呵呵,只是想把自己遇到的各種情形列舉下,希望大家能夠討論每種模型的應(yīng)用范疇和優(yōu)缺點。今天還沒寫完,明天接著總結(jié):wink:
老趙多多提點意見啊

論壇徽章:
0
10 [報告]
發(fā)表于 2011-01-02 19:12 |只看該作者
到目前為止,提到了兩種模型,歡迎大家積極拍磚討論喔。
關(guān)于select 和epoll等模型,歡迎熟悉的朋友積極發(fā)表感受。我明天寫寫基于ICE的模型(也是我目前正在使用的方式)。:wink:
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP