天天看點

[轉載]C#實作的可複用Socket接收/發送共享緩沖區類

在Socket的接收/發送方法:Send()、BeginSend()、Receive()、BeginReceive()中,第一個參數是位元組數數組,表示目前接收資料區或需要發送的資料。普通Socket應用中,往往是接收/發送時建立數組,使用後數組空間由托管堆回收(Socket關閉後其關聯的緩沖區情況類似)。顯然,頻繁建立接收/發送緩沖區将在托管堆上留下很多的記憶體碎塊,影響系統性能。

事實上,在.NET 2.0平台上的Socket傳統APM(異步程式設計模型)中仍然可用該這個技術。下面是修改的BufferManager類:

上述代碼中,m_maxSessionCount是Socket伺服器最大的可連用戶端Socket數,BufferManager構造函數要求該數以及接收和發送緩沖區的大小,進而建立兩個大的、可重複使用共享緩沖區。

具體使用步驟如下:

建立一個BufferManager對象 m_bufferManager

擷取緩沖區塊索引号:m_bufferBlockIndex = m_bufferManager.GetBufferBlockIndex()

異步接收:先計算出緩沖區偏移位址,然後開始接收

異步發送:先考慮發送串長度,然後決定是否使用緩沖區,見随後的代碼

不使用塊索引号時:m_bufferManager.FreeBufferBlockIndext(m_bufferBlockIndex)回收

下面是申請一個緩沖區索引号的代碼示例:

下面是Socket異步接收資料的代碼示例:

下面是Socket異步發送字元串datagramText的代碼示例:

在資料發送時,如果發送緩沖區大小比實際發送的包長度大,上述異步發送可以使用BufferManager公共緩沖區。否則,需要建立一個發送緩沖區(位元組數組)。此外,用共享緩沖區分多次發送長資料包也是一個可考慮的方案,但實作比較複雜(留待以後解決)。資料接收則直接使用BufferManager,因為長資料包由Socket自動分多次接收,不需要考慮分包及包接收順序等問題。另一個需要注意的是,擷取的緩沖區索引塊号要記住回收它們。

基于事件驅動的SocketAsyncEventArgs性能的改善,不僅與使用共享緩沖區的技術相關,更與其在完成端口(IOCP)共享SocketAsyncEventArgs對象有關,該對象可重複使用。而在傳統的異步Socket處理時,總會建立一個IAsyncResult對象,該對象不可重複使用,且必須調用AsyncWaitHandle.Close()釋放資源。顯然,共享緩沖區技術隻稍稍改善了應用系統的性能,沒有從根本上消除Socket的APM的缺陷。

本文轉自peterzb部落格園部落格,原文連結:http://www.cnblogs.com/peterzb/archive/2009/05/29/1491603.html,如需轉載請自行聯系原作者。