陳李飛
摘要:本文主要討論使用SocketAsyncEventArgs這個(gè)類(lèi),利用完成端口并且結(jié)合異步事件的方式,設(shè)計(jì)一個(gè)服務(wù)端的消息傳送中心,從而提高服務(wù)器端處理高并發(fā)的性能,并避免在異步套接字 I/O 量非常大時(shí)發(fā)生重復(fù)的對(duì)象分配和同步。
關(guān)鍵詞:完成端口;文件傳輸;套接字
中圖分類(lèi)號(hào):TN915.05 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1007-9416(2019)12-0173-02
1 完成端口簡(jiǎn)介
“完成端口”模型是迄今為止最為復(fù)雜的一種I/O模型。然而,假若一個(gè)應(yīng)用程序同時(shí)需要管理為數(shù)眾多的套接字,那么采用這種模型,往往可以達(dá)到最佳的系統(tǒng)性能!但不幸的是,該模型只適用于Windows NT和Windows 2000操作系統(tǒng)[1]。因其設(shè)計(jì)的復(fù)雜性,只有在你的應(yīng)用程序需要同時(shí)管理數(shù)百乃至上千個(gè)套接字的時(shí)候,而且希望隨著系統(tǒng)內(nèi)安裝的CPU數(shù)量的增多,應(yīng)用程序的性能也可以線性提升,才應(yīng)考慮采用“完成端口”模型。要記住的一個(gè)基本準(zhǔn)則是,假如要為Windows NT或Windows 2000開(kāi)發(fā)高性能的服務(wù)器應(yīng)用,同時(shí)希望為大量套接字I/O請(qǐng)求提供服務(wù)(Web服務(wù)器便是這方面的典型例子),那么I/O完成端口模型便是最佳選擇[2]!
在.net中,一旦說(shuō)到完成端口,我們就不得不提到SocketAsync EventArgs這個(gè)高性能的類(lèi),其內(nèi)部是基于完成端口實(shí)現(xiàn)的,然后被微軟提供了諸多封裝,所以使用起來(lái)也比較簡(jiǎn)單一些。由于這個(gè)類(lèi)利用完成端口并且結(jié)合異步事件的方式進(jìn)行設(shè)計(jì)的[3],所以我們可以大致的知道他的一些特點(diǎn)。
2 處理流程
關(guān)于SocketAsyncEventArgs類(lèi),微軟的解釋很多,但是始終離不開(kāi)高性能三個(gè)字。根據(jù)我的理解,如果利用此類(lèi)設(shè)計(jì)一個(gè)服務(wù)端的消息傳送中心,那么其運(yùn)作流程如下[1]:
(1)創(chuàng)建SocketAsyncEventArgs池,并且創(chuàng)建緩沖管理中心,負(fù)責(zé)對(duì)池中的對(duì)象分配緩沖大小。
(2)創(chuàng)建服務(wù)器套接字,并處于監(jiān)聽(tīng)狀態(tài)。同時(shí)創(chuàng)建基于Socket AsyncEventArgs的客戶端接收對(duì)象,接收客戶端的連接。
(3)如果有客戶端連接, 客戶端接收對(duì)象將會(huì)把控制權(quán)移交給數(shù)據(jù)接收對(duì)象,數(shù)據(jù)接收對(duì)象開(kāi)始接收數(shù)據(jù)。
這只是一個(gè)簡(jiǎn)單的流程,從這里我們可以看出,服務(wù)端套接字只是負(fù)責(zé)監(jiān)聽(tīng),一旦有客戶端連接,就會(huì)把連接事件拋給接收對(duì)象;所以客戶端一個(gè)一個(gè)的來(lái),服務(wù)端一個(gè)一個(gè)的拋,性能自然會(huì)好了不少。
3 緩沖
說(shuō)到緩沖,我們很容易理解為一個(gè)存儲(chǔ)池,里面可以放入東西,也可以拿走。在SocketAsyncEventArgs類(lèi)中,我們可以利用其SetBuffer方法初始化緩沖區(qū)[4]。
比如說(shuō):receiveArgs。SetBuffer(new byte[10],0,5);他的意思就是為當(dāng)前接收數(shù)據(jù)對(duì)象設(shè)置的緩沖區(qū)大小為10字節(jié),位置從0開(kāi)始,并且允許接收的最大的數(shù)據(jù)長(zhǎng)度為5字節(jié)。
當(dāng)數(shù)據(jù)被接收,然后寫(xiě)入到緩沖區(qū)的時(shí)候,數(shù)據(jù)會(huì)按照預(yù)先設(shè)定好的緩沖規(guī)則進(jìn)行放置。比如這里我輸入aaaaa,那么在緩沖區(qū)會(huì)放入如下數(shù)據(jù):
但是當(dāng)有新的數(shù)據(jù)再進(jìn)來(lái)的時(shí)候,比如這里我輸入了bbbb,那么緩沖區(qū)就變成了:
如上圖所示,緩沖區(qū)中第五位依然是我們前一次插入的值,所以,在這里我提醒大家,緩沖區(qū)的東西取完之后,一定要重置一下,否則臟數(shù)據(jù)會(huì)導(dǎo)致數(shù)據(jù)錯(cuò)誤。
講到這里,也許有人會(huì)說(shuō),假如我插入aaaaab會(huì)怎么樣,其實(shí),這個(gè)長(zhǎng)度已經(jīng)超過(guò)了緩沖區(qū)的長(zhǎng)度,緩沖區(qū)將會(huì)做截?cái)嗵幚?,然后?dāng)作兩段放入緩存中,首先會(huì)是:
然后會(huì)是:
所以如果這個(gè)時(shí)候你的數(shù)據(jù)沒(méi)有被及時(shí)取走的話,將會(huì)得到最終結(jié)果:
這不,已經(jīng)發(fā)生粘包現(xiàn)象了。
4 拋出方式
說(shuō)完緩沖,這里我們需要說(shuō)到的是服務(wù)端套接字是如何將接收的客戶端通過(guò)事件的方式拋給SocketAsyncEventArgs對(duì)象的。
在進(jìn)行服務(wù)端,我們一般都會(huì)有一個(gè)用于監(jiān)聽(tīng)的套接字,套接字會(huì)利用serverSocket。AcceptAsync(SocketAsyncEventArgs)異步方法注冊(cè)SocketAsyncEventArgs對(duì)象,然后一旦有客戶端連接,就會(huì)激發(fā)SocketAsyncEventArgs對(duì)象的Completed事件,然后,在這個(gè)事件中,serverSocket會(huì)通過(guò)ReceiveAsync(SocketAsync EventArgs)異步方法將數(shù)據(jù)處理的過(guò)程交給另外一個(gè)專(zhuān)門(mén)負(fù)責(zé)數(shù)據(jù)處理的對(duì)象去完成,這樣,客戶端連接,服務(wù)端只負(fù)責(zé)將連接事件拋給SocketAsyncEventArgs對(duì)象即可,比起傳統(tǒng)的編程方式:服務(wù)端既負(fù)責(zé)監(jiān)聽(tīng),又負(fù)責(zé)接收,效率極大的提升。如圖1所示。
5 同步方式
最后說(shuō)到的是同步問(wèn)題,因?yàn)樵诋惒浇换サ南到y(tǒng)中,同步問(wèn)題確實(shí)很重要,尤其是當(dāng)客戶端和服務(wù)器同步的時(shí)候。
客戶端里面的線程同步,我們可以利用AutoResetEvent來(lái)實(shí)現(xiàn),客戶端和服務(wù)端同步的時(shí)候,我們需要AutoResetEvent并且結(jié)合一些標(biāo)記信息來(lái)進(jìn)行,也就是客戶端往服務(wù)器發(fā)送的一些小標(biāo)記,比如1代表可以進(jìn)行,0代表取消等等。
在設(shè)計(jì)的時(shí)候,我們還需要記住的是,代碼的核心只是負(fù)責(zé)數(shù)據(jù)的傳輸,不要加過(guò)多的邏輯判斷在里面,否則會(huì)影響性能,邏輯判斷等最好移到界面處理處來(lái)進(jìn)行。
參考文獻(xiàn)
[1] 楊勇.基于完成端口模型的網(wǎng)絡(luò)服務(wù)器性能優(yōu)化研究[J].科教導(dǎo)刊(下旬),2016(12):35-36+81.
[2] 王允,蘇寧.基于完成端口的高性能.Net網(wǎng)絡(luò)通信服務(wù)器模型[J].信息與電腦(理論版),2016(9):23-24.
[3] 李龍.基于Windows的雷達(dá)系統(tǒng)操控軟件的設(shè)計(jì)與實(shí)現(xiàn)[J].科技信息,2012(21):54-55.
[4] 王璋.基于完成端口模型的大流量服務(wù)器開(kāi)發(fā)模式探究[J].福建電腦,2007(2):45-46.
Design of? File Transfer Based on Completion Port
CHEN Li-fei
(Suzhou Higher Vocational and Technical School,Suzhou? Jiangsu? 215009)
Abstract:This paper mainly discusses how to use socketasynceventargs to design a message transmission center of the server side by using the completion port and combining with asynchronous events, so as to improve the performance of the server side in dealing with high concurrency and avoid repeated object allocation and synchronization when the amount of asynchronous socket I/O is very large.
Key words:completion port;file transfer;socket