邰非 林健偉 張開驍 王國棟
摘要:Select是Windows操作系統(tǒng)提供的一個API函數(shù),它具備強大的網(wǎng)絡探測能力且使用方便。眾所周知,在阻塞模式下網(wǎng)絡通訊可能造成進程掛起,較為可靠的方法是采用非阻塞模式,但Windows底層所提供的socket函數(shù)在非阻塞方式下返回值可信度很低,如果通過Select模式結合超時處理來獲取返回狀態(tài),會大大提升程序返回值的可信度。本文采用java語言來實現(xiàn)一個基于TCP/UDP協(xié)議的級聯(lián)文件傳輸服務器,其中利用Select模式對端口的可讀寫性進行探測。通過實際測試,在有效地防止進程掛起的同時能準確獲取返回值,從而正確判斷端口狀態(tài),從側面增強系統(tǒng)的健壯性與可維護性。
關鍵詞:Select;阻塞模式;非阻塞模式
中圖分類號:TP393 文獻標識碼:A 文章編號:1007-9416(2020)09-0048-03
0 引言
隨著互聯(lián)網(wǎng)的迅猛發(fā)展,網(wǎng)絡應用已經(jīng)越來越廣泛地融入到各行各業(yè),各種傳統(tǒng)設備、業(yè)務模式也正向網(wǎng)絡化、智能化、集成化方向發(fā)展。在其中網(wǎng)絡通訊扮演著一個重要且不可缺少角色,但由于各種軟、硬件及周邊環(huán)境等因素的影響,通訊網(wǎng)絡上的擁塞情況時常發(fā)生,這會造成數(shù)據(jù)在傳輸中產生丟包、抖動等現(xiàn)象,從而造成網(wǎng)絡性能指標下降。
近幾年對網(wǎng)絡擁塞問題的研究及提出的解決方案層出不窮,針對具體應用在一定程度上為提升網(wǎng)絡性能起到了很好的作用。本文則是通過Windows所提供的Select API[1]函數(shù)的功能與特點,結合實際用例,對網(wǎng)絡擁塞所造成的函數(shù)返回值不穩(wěn)定性做了進一步的修正,從而給出穩(wěn)定性、可靠性較高的返回值,為進一步查明網(wǎng)絡擁塞原因并給出解決方案提供了技術上的支持。
1 技術路線背景
1.1 Select簡介
選擇Select可以實現(xiàn)非阻塞式處理方式,此時進程或線程執(zhí)行此函數(shù)時不必等待事件發(fā)生,一旦執(zhí)行肯定返回,其返回值表示函數(shù)執(zhí)行的情況,從中可獲取需要監(jiān)視的文件描述符變化情況即:讀寫正?;蚴钱惓!?/p>
Select[1]的函數(shù)格式:int select(int maxfdp,fd_set *readfds,fd_set*writefds,fd_set *errorfds,struct timeval *timeout);maxfdp為整型參數(shù),在Unix系統(tǒng)中是指文件描述符的范圍,Windows中該參數(shù)值可以不設。*readfds結構體指針,用以存放文件描述符即文件句柄,可以是普通文件也可以是設備、管道、FIFO,主要提供讀狀態(tài)變化。*writefds指針變量則是負責文件句柄寫狀態(tài)獲取。*errorfds為記錄異常狀態(tài)的結構體指針。timeval結構體指針代表以秒或毫秒計量的時間值,這個參數(shù)至關重要,它可以使select處于三種狀態(tài):(1)賦值NULL時是將Select置于阻塞狀態(tài)。(2)賦值為0時表示純粹的非阻塞函數(shù),不管文件描述符是否有變化,都立刻返回繼續(xù)執(zhí)行,文件無變化返回0,有變化返回一個正值。(3)賦值大于0則為超時時間,即select在timeout時間內阻塞,超時時間之內有事件到來就返回了,否則在超時后不管怎樣一定返回,返回值同上述。
1.2 基于Select的服務器架構與流程
圖1所示為級聯(lián)服務器和客戶端的物理部署圖,為了簡單起見,此處只給出了一個客戶端連接狀態(tài),各級服務器上運行的服務進程是相同的,它們之間通過TCP[2-3]連接??蛻舳伺c服務器端下載文件通道則使用UDP[2-3]。
圖2給出了文件查找和傳輸?shù)牧鞒?,服務器首先要進行初始化,客戶端發(fā)起下載文件請求給第一個級聯(lián)服務器,該服務器查詢本地文件,如果有則推送文件,如果沒有則轉發(fā)到下一級級聯(lián)服務器,依此類推直到最后一級級聯(lián)服務器,如果沒有查到文件則仍依次將錯誤信息返回給客戶端。
在服務器與服務器以及服務器與客戶端之間通訊中,我們采用了Select模式去探測可能出現(xiàn)的各種通訊故障,通過返回值及時給出應對處理。部分關鍵代碼[4]如圖3所述。
2 實現(xiàn)算法描述
文件服務器有三個通訊端口:P、P+1、P+2。服務器啟動時P端口進行UDP[2-3]監(jiān)聽,主要負責接收查詢字符協(xié)議。P+1進行TCP[2-3]監(jiān)聽,用以維護服務器間的連接。P+2進行UDP[2-3]監(jiān)聽,響應自客戶端的初始化通知。
考慮到客戶端是不斷變動的,此處用UDP監(jiān)聽是利用其無狀態(tài)特性,如果用TCP則會出現(xiàn)TIME_WAIT,每四分鐘才可重新連接,效率極低。P+1和P+2端口只要其中一個收到上一級服務器的初始化數(shù)據(jù)包,另一個則會自動關閉,從而節(jié)省資源。對于中間(非最后)服務器和客戶端則需要在啟動和查尋時通知下一級服務器,客戶端利用UDP協(xié)議連接下一級服務器的P+2端口,服務器用轉發(fā)端口連接下一級服務器的P+1端口。所有服務器初始化完成后,一個通暢的文件傳輸網(wǎng)絡就構建起來[5]。
客戶端請求發(fā)出到服務器上,服務器將查找本地共享目錄中是否有該文件。沒有則將查找請求發(fā)送到自己的下一服務器。如果有該文件則發(fā)送文件到客戶端。對于非第一服務器,如果有該文件將會把結果發(fā)送到上服務器的TEMP端口,而TEMP端口繼續(xù)轉發(fā)直到客戶端。而當查找請求到最后服務器時,還沒有該文件,將返回字符串“wrong!”到上一服務器的TEMP端口,直到服務器,服務器會給出找不到該文件的提示。
圖4中給出了客戶端、中間服務器、終端服務器關鍵線程調用時序圖[6],客戶端設置了兩類超時,一是初始化通訊超時,另一個則為接收文件超時,主要用以提高交互的效率。服務器端則提供更新實際存儲文件服務器IP地址的線程服務,也是基于效率考慮的。
3 結語
在文件服務器與客戶端程序中使用Select實時對網(wǎng)絡的通訊狀態(tài)進行監(jiān)控,有利于及時獲取網(wǎng)絡狀態(tài),以便做更進一步的優(yōu)化擴展。本文中將這種便捷用于文件傳輸服務器上,從實際使用效果來看能很好地應對網(wǎng)絡異常情況下的策略調整,當然程序還有進一步優(yōu)化的空間,另外這種模式也可以用在其它復雜環(huán)境下的網(wǎng)絡通訊程序之中。
參考文獻
[1] Jeffrey Richter.Windows核心編程(第5版 中文版)[M].北京:清華大學出版社,2008.
[2] W.RICHARD STEVENS.TCP/IP Illustrated Volume 1(The Protocols)[M].北京:機械工業(yè)出版社,2005.
[3] 孫曉剛.面向軟件工程的Visula C++網(wǎng)絡程序開發(fā)[M].北京:清華大學出版社,2004.
[4] BJARNE STROUSTRUP.The C++ Programming Language(special Edition)[M].北京:高等教育出版社,2003.
[5] Martin Fowler.重構:改善既有代碼的設計(中文版)[M].北京:中國電力出版社,2006.
[6] James Rumbaugh.The Unified Modeling Language Reference Manual[M].the United States of America:Addison Wesley Longman,Inc,1998.