深入探析c# Socket轉(zhuǎn)自:http://www.cnblogs.com/tianzhiliang/archive/2010/09/08/1821623.html 最近瀏覽了幾篇有關(guān)Socket發(fā)送消息的文章,發(fā)現(xiàn)大家對(duì)Socket Send方法理解有所偏差,,現(xiàn)將自己在開(kāi)發(fā)過(guò)程中對(duì)Socket的領(lǐng)悟?qū)懗鰜?lái),,以供大家參考。 ?。ㄒ唬┘軜?gòu) 基于TCP協(xié)議的Socket通信,,架構(gòu)類(lèi)似于B/S架構(gòu),一個(gè)Socket通信服務(wù)器,,多個(gè)Socket通信客戶(hù)端,。Socket通信服務(wù)器 啟動(dòng)時(shí),會(huì)建立一個(gè)偵聽(tīng)Socket,,偵聽(tīng)Socket將偵聽(tīng)到的Socket連接傳給接受Socket,,然后由接受Socket完成接受、發(fā)送消息,,當(dāng) Socket存在異常時(shí),,斷開(kāi)連接。在實(shí)際開(kāi)發(fā)項(xiàng)目中,,往往要求Socket通信服務(wù)器能提供高效,、穩(wěn)定的服務(wù),一般會(huì)用到以下技術(shù):雙工通信,、完成端 口,、SAEA、池,、多線程,、異步等。特別是池,,用的比較多,,池一般包括一下幾種: 1)Buffer池,用于集中管控Socket緩沖區(qū),,防止內(nèi)存碎片,。 2)SAEA池,用于集中管控Socket,,重復(fù)利用Socket,。 3)SQL池,用于分離網(wǎng)絡(luò)服務(wù)層與數(shù)據(jù)訪問(wèn)層(SQL的執(zhí)行效率遠(yuǎn)遠(yuǎn)低于網(wǎng)絡(luò)層執(zhí)行效率),。 4)線程池,,用于從線程池中調(diào)用空閑線程執(zhí)行業(yè)務(wù)邏輯,進(jìn)一步提高網(wǎng)絡(luò)層運(yùn)行效率,。
主服務(wù)器接受Socket為一端口,,客戶(hù)端Socket為一端口,這兩個(gè)端口通過(guò)TCP協(xié)議建立連接,,通信基礎(chǔ)系統(tǒng)負(fù)責(zé)管理此連接,,它有兩個(gè)功能: 1)發(fā)送消息 2)接受消息 Socket的Send方法,,并非大家想象中的從一個(gè)端口發(fā)送消息到另一個(gè)端口,,它僅僅是拷貝數(shù)據(jù)到基礎(chǔ)系統(tǒng)的發(fā)送緩沖區(qū),然后由基礎(chǔ)系統(tǒng)將發(fā) 送緩沖區(qū)的數(shù)據(jù)到連接的另一端口,。值得一說(shuō)的是,,這里的拷貝數(shù)據(jù)與異步發(fā)送消息的拷貝是不一樣的,同步發(fā)送的拷貝,,是直接拷貝數(shù)據(jù)到基礎(chǔ)系統(tǒng)緩沖區(qū),,拷貝 完成后返回,在拷貝的過(guò)程中,,執(zhí)行線程會(huì)IO等待, 此種拷貝與Socket自帶的Buffer空間無(wú)關(guān),,但異步發(fā)送消息的拷貝,是將Socket自帶的Buffer空間內(nèi)的所有數(shù)據(jù),,拷貝到基礎(chǔ)系統(tǒng)發(fā)送緩 沖區(qū),,并立即返回,執(zhí)行線程無(wú)需IO等待,,所以異步發(fā)送在發(fā)送前必須執(zhí)行SetBuffer方法,,拷貝完成后,會(huì)觸發(fā)你自定義回調(diào)函數(shù) ProcessSend,,在ProcessSend方法中,,調(diào)用SetBuffer方法,重新初始化Buffer空間,。
口說(shuō)無(wú)憑,,下面給個(gè)例子: 服務(wù)器端: 客戶(hù)端: 解釋?zhuān)?/p>
客戶(hù)端第一次發(fā)送數(shù)據(jù):1234567890。 客戶(hù)端第一個(gè)接受數(shù)據(jù):1234567890,,該數(shù)據(jù)由服務(wù)端用Send同步方法發(fā)送返回,。 客戶(hù)端第二個(gè)接受數(shù)據(jù):1234567890,該數(shù)據(jù)由服務(wù)端用Send異步方法發(fā)送返回,。
以上似乎沒(méi)什么異常,,好,接下來(lái),,我只發(fā)送abc,。 客戶(hù)端第一個(gè)接受數(shù)據(jù):abc,理所當(dāng)然,,沒(méi)什么問(wèn)題,。 客戶(hù)端第二個(gè)接受數(shù)據(jù):abc4567890,!為什么呢?應(yīng)該是abc才對(duì)呀,!
好,,現(xiàn)在為大家解釋一下: 異步發(fā)送是將其Buffer空間中所有數(shù)據(jù)拷貝到基礎(chǔ)系統(tǒng)發(fā)送緩沖區(qū),第一次拷貝1234567890到發(fā)送緩沖區(qū),,所以收到1234567890,,第二次拷貝abc到發(fā)送緩沖區(qū),替換了先前的123,,所以收到abc4567890,,大家明白的?
源碼:
BufferManager
SocketAsyncEventArgsPool
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; class AsyncUserToken { public Socket Socket; }
Server
Program |
|