褚凱 牛紅巖 王志田
摘要:為滿足系統(tǒng)對服務(wù)端的性能要求,采用了完成端口模型,介紹了完成端口的工作原理,給出了系統(tǒng)的工作流程,對關(guān)鍵問題進(jìn)行了分析,設(shè)計(jì)了服務(wù)端的通信框架,實(shí)現(xiàn)了對大量并發(fā)客戶的桌面投放系統(tǒng)。
關(guān)鍵詞:完成端口;多線程;信息重組;投放系統(tǒng)
中圖分類號:TP311 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2014)22-5213-04
隨著經(jīng)濟(jì)和網(wǎng)絡(luò)的不斷發(fā)展,桌面廣告投放系統(tǒng)已經(jīng)成為廣告宣傳的重要方式。個(gè)人電腦已經(jīng)成為辦公、收銀等處理業(yè)務(wù)的客戶終端,客戶終端桌面也是一張名品。利用桌面廣告投放系統(tǒng)可將這些客戶終端的桌面設(shè)置為統(tǒng)一形式,無形中加大了宣傳力度。
桌面廣告投放系統(tǒng)采用C/S模式,核心是解決一對多的大并發(fā)網(wǎng)絡(luò)連接問題[1]。為了解決客戶端大量網(wǎng)絡(luò)連接服務(wù)端的并發(fā)問題,本系統(tǒng)采用完成端口IOCP(I/O Completion Port)模型進(jìn)行開發(fā)。IOCP是微軟在Winsock2.0中引入的網(wǎng)絡(luò)編程模型。它是目前編寫高性能,易擴(kuò)展的C/S網(wǎng)絡(luò)服務(wù)器中最好網(wǎng)絡(luò)模型[2]。
1 桌面廣告系統(tǒng)結(jié)構(gòu)
桌面廣告系統(tǒng)采用C/S網(wǎng)絡(luò)模型并基于互聯(lián)網(wǎng)實(shí)現(xiàn)服務(wù)端和客戶端的網(wǎng)絡(luò)通信。桌面廣告系統(tǒng)包括客戶端、服務(wù)器端和互聯(lián)網(wǎng),客戶端為需要設(shè)置桌面廣告的計(jì)算機(jī),服務(wù)端為產(chǎn)生廣告桌面的服務(wù)器,通常架設(shè)在個(gè)人計(jì)算機(jī)上。系統(tǒng)結(jié)構(gòu)如圖1所示。
2 IOCP機(jī)制的工作原理
完成端口(IOCP)的核心原理就是將綁定到IOCP的socket發(fā)出的異步I/O請求投遞到消息隊(duì)列中,利用一定數(shù)量的工作線程從消息隊(duì)列中取出消息并進(jìn)行處理,并在工作者線程中返回中間數(shù)據(jù)。IOCP工作框架如圖2所示。
2.1 完成端口
完成端口是windows的內(nèi)核對象,稱其為完成端口,是因?yàn)橄到y(tǒng)在網(wǎng)絡(luò)I/O操作“完成”之后才會發(fā)出通知。在接到系統(tǒng)的通知的時(shí),其實(shí)網(wǎng)絡(luò)操作已經(jīng)完成,此時(shí),系統(tǒng)已經(jīng)自動(dòng)完成網(wǎng)絡(luò)數(shù)據(jù)的接收(而不是像傳統(tǒng)socket是有網(wǎng)絡(luò)數(shù)據(jù)到來)或者系統(tǒng)已經(jīng)自動(dòng)接受了客戶端的連接請求等等,應(yīng)用程序的工作就是直接處理接收的網(wǎng)絡(luò)數(shù)據(jù)或者判斷新連入的客戶端。
完成端口的實(shí)際處理方式是:依據(jù)CPU數(shù)量N,建立2*N個(gè)線程。這些線程能夠充分利用CPU資源,從某一個(gè)公共消息隊(duì)列中循環(huán)讀取數(shù)據(jù),當(dāng)隊(duì)列中無數(shù)據(jù)時(shí),一直處于等待狀態(tài)。當(dāng)客戶數(shù)據(jù)或請求到來時(shí),應(yīng)用程序?qū)⒖蛻粽埱笸斗诺皆摴蚕㈥?duì)列中。線程們依次逐個(gè)從該消息隊(duì)列中取出用戶數(shù)據(jù)并進(jìn)行處理。這種處理數(shù)據(jù)的方式就徹底解決了異步通信中的負(fù)載均衡問題。因?yàn)樗ㄟ^一定數(shù)量的線程合理的處理大量客戶端的請求數(shù)據(jù),且當(dāng)線程處于空閑時(shí)期會被系統(tǒng)掛起,不耗費(fèi)CPU資源。這個(gè)作為交換的關(guān)鍵消息隊(duì)列就是完成端口[3]。
2.2 重疊I/O
利用完成端口實(shí)現(xiàn)異步通信,必須使用到極其重要的I/O數(shù)據(jù)結(jié)構(gòu),即重疊(Overlapped)結(jié)構(gòu)。
重疊結(jié)構(gòu)是異步通信機(jī)制實(shí)現(xiàn)的一個(gè)核心數(shù)據(jù)結(jié)構(gòu),絕大多數(shù)網(wǎng)絡(luò)操作如發(fā)送和接收,都將被WSASend()和WSARecv()所代替,每個(gè)參數(shù)都會包含一個(gè)重疊結(jié)構(gòu)。在使用重疊I/O的異步機(jī)制時(shí),系統(tǒng)內(nèi)核要求每個(gè)網(wǎng)絡(luò)操作都必須有唯一的ID號。而重疊結(jié)構(gòu)就相當(dāng)于是一個(gè)網(wǎng)絡(luò)操作的ID號,內(nèi)核中進(jìn)入重疊I/O后,按需求處理完畢,再根據(jù)其ID號,把對應(yīng)的數(shù)據(jù)傳到內(nèi)核外。
3 系統(tǒng)的工作流程及實(shí)現(xiàn)
3.1 工作流程
利用IOCP模型開發(fā)網(wǎng)絡(luò)服務(wù)端,主要的工作就是創(chuàng)建主線程和工作線程。在異步通信中,主線程主要的任務(wù)就是初始化時(shí)建立通信框架,即創(chuàng)建并監(jiān)聽套接字,創(chuàng)建工作線程,等待客戶端連接。工作線程主要處理IOCP上完成的網(wǎng)絡(luò)操作。本系統(tǒng)的服務(wù)端功能模塊在VC6環(huán)境中開發(fā),利用socket模型中的TCP/IP協(xié)議,網(wǎng)絡(luò)傳輸工作過程如圖3所示流程。
3.2 實(shí)現(xiàn)過程
定義單句柄數(shù)據(jù)結(jié)構(gòu)體,用于每一個(gè)完成端口,也就是每一個(gè)Socket的參數(shù)。具體結(jié)構(gòu)定義如下:
大體上來講,使用完成端口只用遵循如下幾個(gè)步驟:
1) 調(diào)用 CreateIoCompletionPort() 函數(shù)創(chuàng)建一個(gè)完成端口,而且在一般情況下,只需要建立一個(gè)完成端口。
2) 根據(jù)系統(tǒng)中有多少個(gè)處理器,就建立多少個(gè)工作者線程;
3) 接收客戶端socket連接,共有兩種處理方法:一是啟動(dòng)一個(gè)獨(dú)立的線程,接受客戶端的連接請求;二是使用異步AcceptEx()請求。該文采用第二種方式。
4) 每當(dāng)有客戶端連入的時(shí)候,調(diào)用CreateIoCompletionPort()函數(shù),這里卻不是新建立完成端口了,而是把新連入的Socket(也就是前面所謂的設(shè)備句柄),與目前的完成端口綁定在一起。至此,就已經(jīng)完成了完成端口的相關(guān)部署工作了。
5) 客戶端連入之后,可以在這個(gè)Socket上提交一個(gè)網(wǎng)絡(luò)請求,例如WSARecv(),然后系統(tǒng)就會自動(dòng)去執(zhí)行接收數(shù)據(jù)的操作;
6) 而此時(shí),預(yù)先準(zhǔn)備的那幾個(gè)Worker線程開始工作,都需要分別調(diào)用GetQueuedCompletionStatus() 函數(shù)在掃描完成端口的隊(duì)列里是否有網(wǎng)絡(luò)通信的請求存在(例如讀取數(shù)據(jù),發(fā)送數(shù)據(jù)等),一旦有的話,就將這個(gè)請求從完成端口的隊(duì)列中取回來,繼續(xù)執(zhí)行本線程中后面的處理代碼,處理完畢之后,可以再繼續(xù)投遞下一個(gè)網(wǎng)絡(luò)通信的請求,如此循環(huán)。
4 關(guān)鍵問題處理
4.1服務(wù)器搭建
在互聯(lián)網(wǎng)上通過C/S模型實(shí)現(xiàn)網(wǎng)絡(luò)通信,首要的問題是服務(wù)器的搭建。普通使用者的需要的是方便、便宜的服務(wù)器。
本系統(tǒng)服務(wù)端所在主機(jī)通過使用花生殼動(dòng)態(tài)域名6.0將本地主機(jī)設(shè)置為服務(wù)器,如圖4所示?;ㄉ鷼?dòng)態(tài)域名軟件通過注冊的域名動(dòng)態(tài)生成本機(jī)的IP地址,客戶端以服務(wù)器域名為參數(shù)利用API函數(shù)gethostbyname()獲得服務(wù)器的IP,通過指定的端口與服務(wù)端建立網(wǎng)絡(luò)連接。
4.2包排序接收信息重組處理
在接收各子系統(tǒng)網(wǎng)絡(luò)報(bào)文數(shù)據(jù)時(shí),由于TCP/IP協(xié)議對數(shù)據(jù)的封裝操作,導(dǎo)致報(bào)文數(shù)據(jù)在網(wǎng)絡(luò)傳輸過程重新組合、打包發(fā)送,存在以下情況:1一幀數(shù)據(jù)被拆分,附在其他報(bào)文數(shù)據(jù)的幀頭或者幀尾打包;2前一幀數(shù)據(jù)同下一幀或幾幀報(bào)文一起打包。為避免出現(xiàn)采用網(wǎng)絡(luò)傳送數(shù)據(jù)過程中的“丟幀”現(xiàn)象,根據(jù)數(shù)據(jù)幀的報(bào)文結(jié)構(gòu),對接收的報(bào)文數(shù)據(jù)進(jìn)行解析處理,重新組合成一幀完整的報(bào)文,處理流程如圖5所示[4]。
4.3 傳送文件
利用Winsock提供的專門傳輸文件和內(nèi)存數(shù)據(jù)的函數(shù)TransmitFile()傳輸時(shí),只需要傳遞已打開的文件句柄和要發(fā)送的字節(jié)數(shù)。轉(zhuǎn)換模式操作只在調(diào)用CreateFile()打開文件時(shí)發(fā)生一次,然后TransmitFile()再發(fā)生一次。這樣的效率相比每次都調(diào)用ReadFile()和WSASend()都會涉及一次從用戶模式到內(nèi)核模式的轉(zhuǎn)換要高多了。
5 結(jié)論
本系統(tǒng)服務(wù)端采用IOCP模型,只需要少量的工作線程來完成大量的網(wǎng)絡(luò)操作,且線程的數(shù)量隨CPU數(shù)量線性增加。該文設(shè)計(jì)的桌面廣告投放系統(tǒng)可以高效得處理多并發(fā),解決了客戶端連接量巨大,小容量數(shù)據(jù)頻繁收發(fā)的問題,實(shí)現(xiàn)了桌面投放系統(tǒng)的初步功能。通過測試,該系統(tǒng)可以滿足大并發(fā)量的桌面投放要求。
參考文獻(xiàn):
[1] 王震,徐博,等.單客戶機(jī)-多服務(wù)器模式下IOCP的應(yīng)用與研究[J].計(jì)算機(jī)科學(xué),2011(10):385-386.
[2] Jose Vitor . Another TCP echo server using IOCP [EB/OL]. (2013-03-27). http://www.codeproject.com/Tips/95363/Another-TCP-echo-server-using-IOCP.
[3] 樹愛兵,徐棱,等.IOCP機(jī)制在交通信號控制系統(tǒng)通信服務(wù)器中的應(yīng)用[J].微型電腦應(yīng)用,2012,28(7):55-57.
[4] 褚凱,楊茜.光電火控實(shí)時(shí)信息處理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[J].四川兵工學(xué)報(bào),2012(3).