陳李飛



摘要:本文主要討論使用SocketAsyncEventArgs這個類,利用完成端口并且結合異步事件的方式,設計一個服務端的消息傳送中心,從而提高服務器端處理高并發的性能,并避免在異步套接字 I/O 量非常大時發生重復的對象分配和同步。
關鍵詞:完成端口;文件傳輸;套接字
中圖分類號:TN915.05 文獻標識碼:A 文章編號:1007-9416(2019)12-0173-02
1 完成端口簡介
“完成端口”模型是迄今為止最為復雜的一種I/O模型。然而,假若一個應用程序同時需要管理為數眾多的套接字,那么采用這種模型,往往可以達到最佳的系統性能!但不幸的是,該模型只適用于Windows NT和Windows 2000操作系統[1]。因其設計的復雜性,只有在你的應用程序需要同時管理數百乃至上千個套接字的時候,而且希望隨著系統內安裝的CPU數量的增多,應用程序的性能也可以線性提升,才應考慮采用“完成端口”模型。要記住的一個基本準則是,假如要為Windows NT或Windows 2000開發高性能的服務器應用,同時希望為大量套接字I/O請求提供服務(Web服務器便是這方面的典型例子),那么I/O完成端口模型便是最佳選擇[2]!
在.net中,一旦說到完成端口,我們就不得不提到SocketAsync EventArgs這個高性能的類,其內部是基于完成端口實現的,然后被微軟提供了諸多封裝,所以使用起來也比較簡單一些。由于這個類利用完成端口并且結合異步事件的方式進行設計的[3],所以我們可以大致的知道他的一些特點。
2 處理流程
關于SocketAsyncEventArgs類,微軟的解釋很多,但是始終離不開高性能三個字。根據我的理解,如果利用此類設計一個服務端的消息傳送中心,那么其運作流程如下[1]:
(1)創建SocketAsyncEventArgs池,并且創建緩沖管理中心,負責對池中的對象分配緩沖大小。
(2)創建服務器套接字,并處于監聽狀態。同時創建基于Socket AsyncEventArgs的客戶端接收對象,接收客戶端的連接。
(3)如果有客戶端連接, 客戶端接收對象將會把控制權移交給數據接收對象,數據接收對象開始接收數據。
這只是一個簡單的流程,從這里我們可以看出,服務端套接字只是負責監聽,一旦有客戶端連接,就會把連接事件拋給接收對象;所以客戶端一個一個的來,服務端一個一個的拋,性能自然會好了不少。
3 緩沖
說到緩沖,我們很容易理解為一個存儲池,里面可以放入東西,也可以拿走。在SocketAsyncEventArgs類中,我們可以利用其SetBuffer方法初始化緩沖區[4]。
比如說:receiveArgs。SetBuffer(new byte[10],0,5);他的意思就是為當前接收數據對象設置的緩沖區大小為10字節,位置從0開始,并且允許接收的最大的數據長度為5字節。
當數據被接收,然后寫入到緩沖區的時候,數據會按照預先設定好的緩沖規則進行放置。比如這里我輸入aaaaa,那么在緩沖區會放入如下數據:
但是當有新的數據再進來的時候,比如這里我輸入了bbbb,那么緩沖區就變成了:
如上圖所示,緩沖區中第五位依然是我們前一次插入的值,所以,在這里我提醒大家,緩沖區的東西取完之后,一定要重置一下,否則臟數據會導致數據錯誤。
講到這里,也許有人會說,假如我插入aaaaab會怎么樣,其實,這個長度已經超過了緩沖區的長度,緩沖區將會做截斷處理,然后當作兩段放入緩存中,首先會是:
然后會是:
所以如果這個時候你的數據沒有被及時取走的話,將會得到最終結果:
這不,已經發生粘包現象了。
4 拋出方式
說完緩沖,這里我們需要說到的是服務端套接字是如何將接收的客戶端通過事件的方式拋給SocketAsyncEventArgs對象的。
在進行服務端,我們一般都會有一個用于監聽的套接字,套接字會利用serverSocket。AcceptAsync(SocketAsyncEventArgs)異步方法注冊SocketAsyncEventArgs對象,然后一旦有客戶端連接,就會激發SocketAsyncEventArgs對象的Completed事件,然后,在這個事件中,serverSocket會通過ReceiveAsync(SocketAsync EventArgs)異步方法將數據處理的過程交給另外一個專門負責數據處理的對象去完成,這樣,客戶端連接,服務端只負責將連接事件拋給SocketAsyncEventArgs對象即可,比起傳統的編程方式:服務端既負責監聽,又負責接收,效率極大的提升。如圖1所示。
5 同步方式
最后說到的是同步問題,因為在異步交互的系統中,同步問題確實很重要,尤其是當客戶端和服務器同步的時候。
客戶端里面的線程同步,我們可以利用AutoResetEvent來實現,客戶端和服務端同步的時候,我們需要AutoResetEvent并且結合一些標記信息來進行,也就是客戶端往服務器發送的一些小標記,比如1代表可以進行,0代表取消等等。
在設計的時候,我們還需要記住的是,代碼的核心只是負責數據的傳輸,不要加過多的邏輯判斷在里面,否則會影響性能,邏輯判斷等最好移到界面處理處來進行。
參考文獻
[1] 楊勇.基于完成端口模型的網絡服務器性能優化研究[J].科教導刊(下旬),2016(12):35-36+81.
[2] 王允,蘇寧.基于完成端口的高性能.Net網絡通信服務器模型[J].信息與電腦(理論版),2016(9):23-24.
[3] 李龍.基于Windows的雷達系統操控軟件的設計與實現[J].科技信息,2012(21):54-55.
[4] 王璋.基于完成端口模型的大流量服務器開發模式探究[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