ascent的網路模組簡析

來源:互聯網
上載者:User

本文是解讀ASIO之前的一碟小菜。。。

ascent 2010的網路模組代碼採用了IOCP,代碼量很小。

帶著以下問題溜了一遍:

 

1.IOCP的亂序問題

如果同時對一個socket投遞多個recv或者send請求,那麼應用程式層會將TCP辛辛苦苦保證的有序

給打亂。

解決辦法很簡單,串列投遞。

這對於伺服器程式來說是可行的,畢竟它管理的是成百上千個sockets,每個2請求,那IOCP要處理

的也很多了。

ascent也是這麼做的(從socket類只含有兩個overlap對象一眼看出)。

但不是強制:發生了重複投遞,它只是寫了一條錯誤記錄檔。

 

 

 

2. send操作能否避開鎖?(recv無須鎖是很好做的,不提)

 事實上我覺得是可以的,至少epoll是絕對可以的,邊寫邊想IOCP是否也可以。

從線程的角度看,一條串連的發送緩衝區的消費者是網路線程,生產者是邏輯線程。

 即發送資料一定是邏輯線程發起的(前提是心跳包也要一併移給邏輯線程處理);

那麼緩衝區的讀遊標是由網路線程修改,寫遊標是由邏輯線程修改。

要做到無鎖,一定要保證共用變數只會被一個線程修改,且為volatile類型;

邏輯線程投遞寫請求,將資料放入發送緩衝,修改寫遊標;

對於IOCP來說,網路工作者線程可能有多個(一般來說是CPU數目的兩倍),

多個網路線程阻塞在GetQueuedCompletionStatus函數,儘管執行send請求的成功回調

不是由某個固定網路線程執行,但在同一時刻send請求的回調一定是由某一個線程單獨處理,

並調整讀遊標。

所以感覺iocp方式下,socket的發送緩衝區也無須鎖。

(也許考慮還不是很全面,待修正)

 

asent中使用了鎖來保護髮送緩衝區,但我認為是它的緩衝區結構設計問題導致的(很複雜,做成了兩段緩衝),如果做成簡單的不可擴充的

足夠大的環形緩衝區,是無須鎖的。(帶來一個問題:由於發送的資料可能不是在連續緩衝,發送操作請調用類似writev的函數,

當然WINDOWS支援的很好,WSASend與WSABUF共同實現gather-write)

在邏輯線程發送資料時,如果檢測到並沒有send操作正在掛起中,那麼就直接WSASend

 

3.是否單獨啟動LISTEN線程

ascent確實單獨啟動了一個監聽線程。不過有點惡的是,如果啟動了兩個監聽socket,那就啟動兩個監聽線程,

太浪費了。

監聽線程阻塞ACCEPT,並將新串連與IOCP關聯,同時投遞第一個RECV請求。

 

另記:

為什麼非阻塞socket,send也會阻塞?
A端發資料,B端不調用recv;
於是一會兒A端的發送緩衝區滿了,竟然阻塞在send調用;而不是返回-1和EAGAIN?

 

必須send時候指定MSG_DONTWAIT。。儘管是非阻塞socket
但是man手冊說了,設定了O_NONBLOCK,就不用指定這個。
艸,誤導人

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.