基于IOCP的局域網(wǎng)監(jiān)控系統(tǒng)_第1頁
基于IOCP的局域網(wǎng)監(jiān)控系統(tǒng)_第2頁
基于IOCP的局域網(wǎng)監(jiān)控系統(tǒng)_第3頁
基于IOCP的局域網(wǎng)監(jiān)控系統(tǒng)_第4頁
基于IOCP的局域網(wǎng)監(jiān)控系統(tǒng)_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、基于IOCP的局域網(wǎng)監(jiān)控系統(tǒng)          摘要 本文介紹了一種在WINDOWS平臺上比較成熟的I/O方法-完成端口,提出了通過使用IOCP機制和旁視列表技術建立網(wǎng)絡服務器模型的方法,實現(xiàn)了利用為數(shù)不多的線程為成千上萬的客戶同時提供網(wǎng)絡服務,解決了大多數(shù)網(wǎng)絡服務器連接大量客戶端和處理大量數(shù)據(jù)時存在的問題,獲得了極好的性能和強大的擴展能力。文章給出了基于indows 2000平臺的局域網(wǎng)監(jiān)控系統(tǒng)中網(wǎng)絡服務器的設計與實現(xiàn)過程。    關鍵詞 完成端口;旁視列表;網(wǎng)絡服務器;VC+

2、60;1  引言    在局域網(wǎng)遠程監(jiān)控系統(tǒng)中,網(wǎng)絡管理中心需要同時監(jiān)控每個客戶端計算機的運行情況,將遠程監(jiān)控畫面顯示在管理中心的電腦屏幕上。網(wǎng)絡服務器要求實現(xiàn)定時截獲客戶端計算機上的屏幕數(shù)據(jù)與正在運行程序的數(shù)據(jù),定時截取客戶端屏幕圖像,并將截獲的數(shù)據(jù)和圖像保存在數(shù)據(jù)庫中等功能。在較大型局域網(wǎng)中有幾百上千個客戶端,需要對大量的客戶端數(shù)據(jù)進行處理。因此如何讓網(wǎng)絡服務器同時為多個客戶端服務,但又不喪失整體的性能成為開發(fā)的難點。本文采用了I/O完成端口、旁視列表等技術,設計了一種高效的網(wǎng)絡服務器,讓此問題得到了有效的解決。2  IOCP機制 

3、;   IOCP(I/O Completion Port輸入/輸出完成端口)是一種能夠合理利用與管理多線程的機制。該機制使用完成端口,用一定數(shù)量的線程處理重疊I/O(Overlapped I/O)的技術,幫助處理大量客戶端請求的網(wǎng)絡服務問題,特別適合于開發(fā)網(wǎng)絡服務器一類的應用程序,并可使系統(tǒng)的性能達到較佳狀態(tài)。IOCP模型圖如圖1所示。圖1 完成端口工作模式    完成端口模式要求創(chuàng)建一個Win32完成端口對象來對重疊I/O請求進行管理,并通過創(chuàng)建一定數(shù)量的工作者線程(WorkThread),來為已經(jīng)完成的重疊I/O請求提供服務。其實,可以把完

4、成端口看成系統(tǒng)維護的一個隊列,操作系統(tǒng)把重疊I/O操作完成的事件通知放入該隊列,由于是“操作完成”的事件通知,故取名為“完成端口”。一個完成端口被創(chuàng)建以后,可以和多個文件句柄進行關聯(lián)(文件句柄可以是真正的文件句柄,也可以是Socket句柄或命名管道),并在關聯(lián)后的句柄上進行重疊I/O操作。當I/O操作完成后,一個重疊I/O完成的事件通知就會被排在此端口的完成隊列上,此時,某個工作者線程將會被喚醒來為完成端口服務,執(zhí)行特定的處理工作。一般來說,一個應用程序可以創(chuàng)建多個工作者線程來處理完成端口上的通知事件,工作者線程的數(shù)量依賴于程序的具體需要。  3  數(shù)據(jù)庫同步機制實現(xiàn)過程:

5、(系統(tǒng)結構圖如圖2)圖2 系統(tǒng)結構圖    (1)整體系統(tǒng)安裝初始,各個同步端的數(shù)據(jù)庫初始化為一致。    (2)數(shù)據(jù)服務器維護各個同步端的SQL隊列,不斷檢查是否有操作項,然后將各項操作依序發(fā)送至各個在線的同步端。    (3)在線同步端收到后,置入SQL隊列,將SQL隊列按操作發(fā)生時間先后排序    (4)在線同步端將SQL隊列中的各項操作依序執(zhí)行并通知服務器執(zhí)行的結果。服務器收到后將該項操作從該同步端的SQL隊列中刪除。    (5)某一在

6、線同步端執(zhí)行非讀的SQL操作后,向服務器發(fā)送該操作,服務器將該操作放入除了此同步端外的其他同步端的SQL隊列中,并放入歷史SQL文件,然后轉到第2步     (6)有新同步端注冊入系統(tǒng)后,將從數(shù)據(jù)服務器(數(shù)據(jù)服務器同時建立該同步端的SQL隊列)下載歷史SQL文件,并執(zhí)行其中各項操作。    (7)某同步端選擇注銷,數(shù)據(jù)服務器刪除該同步端的SQL隊列。4  內(nèi)存分配機制    在該系統(tǒng)中內(nèi)存的分配和釋放比較頻繁,為了比較高效分配釋放數(shù)據(jù),采用一種稱作Lookaside List(旁視列表)的數(shù)據(jù)結

7、構。在該系統(tǒng)中用于單句柄數(shù)據(jù)和重疊操作數(shù)據(jù)(完成鍵)的分配和釋放。Lookaside List的原理是在分配一塊數(shù)據(jù)空間前,先查看回收鏈表中是否有數(shù)據(jù)空間指針,如果有則不需要調(diào)用系統(tǒng)的內(nèi)存分配,直接使用回收鏈表中的該指針指向的數(shù)據(jù)空間,并將回收鏈表中該指針節(jié)點移除,當使用完數(shù)據(jù)空間后,也不必調(diào)系統(tǒng)的內(nèi)存釋放,而將該數(shù)據(jù)空間指針移入回收鏈表。在進程最終結束后才將回收鏈表中的所有指針指向的數(shù)據(jù)空間釋放。從而大大減低程序在運行期的頻繁內(nèi)存分配和釋放產(chǎn)生的開銷。5  實現(xiàn)過程5.1 初始化    讀取服務器配置文件,初始化客戶端連接鏈表;建立完成端口,根據(jù)CPU

8、個數(shù)建立等待和接受完成通知的線程;初始化WinSock接口,建立偵聽SOCKET;取擴展函數(shù)AcceptEx;關聯(lián)完成端口到偵聽SOCKET;綁定和偵聽。5.2 啟動服務    (1)建立網(wǎng)絡事件、設置該網(wǎng)絡事件為偵聽SOCKET的ACCEPT網(wǎng)絡事件,這樣當AcceptEx一次性分配的N個預備SOCKET由于滿足不斷上來的TCP連接而耗盡,并有新的TCP連接請求時,就會觸發(fā)偵聽SOCKET的ACCEPT事件,服務器就會在這個時機調(diào)用AcceptEx再次分配N個新的預備SOCKET以滿足新的TCP連接請求。在該系統(tǒng)中,N=10。   

9、 (2)分配的N個預備SOCKET    (3)建立檢查和分配線程,該線程作用:等待ACCEPT網(wǎng)絡事件以分配新的預備SOCKET;定時檢測和掛斷未收發(fā)任何數(shù)據(jù)且超時連接的TCP連接,防止DoS(拒絕服務)攻擊。5.3完成通知線程內(nèi)部處理while (TRUE)         /等待完成端口的通知                

10、;   bSuccess = GetQueuedCompletionStatus(                                         

11、60;                                                 

12、60;           pThis->m_hCOP,                                    

13、60;                                                 

14、60;                &dwNumberBytes,                               &

15、#160;                                                 &

16、#160;                     (PULONG_PTR )&lpHandleContext,                       &#

17、160;                                                 &#

18、160;                             &lpOverlapped,                  &

19、#160;                                                 &

20、#160;                                  INFINITE              

21、0;                                                 

22、0;                                      );            &

23、#160;       if (!bSuccess)                   pThis->m_strLog.Format("GetQueuedCompletionStatus() 失敗:%d", GetLastError();        

24、;                    Log(pThis->m_strLog);                          

25、0;  PPER_IO_CONTEXT lpPerIoContext = (PPER _IO_CONTEXT)lpOverlapped;                            lpPerIoContext->pNext = NULL;     &#

26、160;                      pThis->InsertToLookaside(lpPerIoContext, NULL);                    

27、;        lpHandleContext->pNext = NULL;                            pThis->InsertToLookaside(NULL, lpHandleContext); 

28、60;                           continue;                   /如果外部發(fā)送空的單句柄數(shù)據(jù)指針,則退出完成

29、通知線程                   if (NULL = lpHandleContext)                            &#

30、160;                         return 0;                   /將完成鍵轉換為自己格式的數(shù)據(jù)指針  

31、0;                PPER_IO_CONTEXT lpPerIoContext = (PPER_IO_ CONTEXT)lpOverlapped;/這種情況表示客戶端自己掛斷連接                   if(IoAccept != lpP

32、erIoContext->IoOperation)                                              &

33、#160; if(0 = dwNumberBytes)                                              &#

34、160;                  shutdown(lpPerIoContext->sClient, SD_BOTH);                        

35、60;            closesocket(lpPerIoContext->sClient);                               

36、0;     lpPerIoContext->pNext = NULL;                               pThis->InsertToLookaside(lpPerIoCon text, NULL);  &#

37、160;                                  lpHandleContext->pNext = NULL;          

38、0;                          pThis->InsertToLookaside(NULL, lpHandleContext);                

39、                                                   

40、;       pThis->DecreaseClientNum();                                       

41、60;                                  continue;               

42、;                                                    HA

43、NDLE hResult;                   PPER_HANDLE_CONTEXT lpNewperHandleContext;/判斷該通知為哪種類型的操作的結果                   switch(lpP

44、erIoContext->IoOperation)                   /接受新的TCP連接                   case IoAccept:     

45、                       pThis->IncreaseClientNum();                 EnterCriticalSection(&pThis->m_ ListCr

46、iSection);                         pThis->ReleaseConnectionNode(lpPerIoContext);                &

47、#160;            LeaveCriticalSection(&pThis-> m_ListCriSection);/將偵聽SOCKET的屬性復制給客戶端SOCKET, 因為accept 創(chuàng)建的 socket 會自動繼承偵聽 socket 的屬性,而AcceptEx不會    nResult = setsockopt(    &#

48、160;                       lpPerIoContext->sClient,                         &

49、#160;      SOL_SOCKET,                           SO_UPDATE_ACCEPT_CONTEXT,             

50、60;                 (char *)&pThis->m_ListenSocket,                           sizeof(pThis-&g

51、t;m_ListenSocket)                               );                 

52、60; if(SOCKET_ERROR = nResult)                                              

53、0; pThis->m_strLog.Format("客戶(ID=%d) SO_ UPDATE_ACCEPT_CONTEXT 失敗:%d",                             lpPerIoContext->unId, WSAGetLastError(); 

54、0;              Log(pThis->m_strLog);                       closesocket(lpPerIoContext->sClient);      &

55、#160;                     lpPerIoContext->pNext = NULL;                      pThis->InsertToLookasi

56、de(lpPerIoContext, NULL);                             pThis->DecreaseClientNum();            

57、0;                                                  

58、60; continue;           /為新的SOCKET分配單句柄數(shù)據(jù)           lpNewperHandleContext=pThis->GetHandleFrom Lookaside();           if (NULL = lpNewperHandleContext)  

59、;                              lpNewperHandleContext = (PPER_HANDLE_ CONTEXT)HeapAlloc(              

60、;                GetProcessHeap(),                              HEAP_ZERO_MEMORY, 

61、60;                            sizeof(PER_HANDLE_CONTEXT)                   

62、;           );                   if (NULL = lpNewperHandleContext)                

63、60;                                pThis->m_strLog.Format("HeapAlloc() 失敗");           

64、                   Log(pThis->m_strLog);                            

65、0;                                                shutdown(lpPerIoContext-&

66、gt;sClient, SD_BOTH);                              closesocket(lpPerIoContext->sClient);           

67、60;                  lpPerIoContext->pNext = NULL;                            

68、0; pThis->InsertToLookaside(lpPerIoContext, NULL);                                pThis->DecreaseClientNum();      

69、;                                                  

70、0;                           continue;                      

71、                                                   

72、0;        /將新的SOCKET關聯(lián)到同一完成端口上                   lpNewperHandleContext->IoSocket = lpPerIo Context  ->sClient;         

73、          lpNewperHandleContext->pNext = NULL;                                   &

74、#160;                                       hResult = CreateIoCompletionPort(      &#

75、160;                               (HANDLE)lpPerIoContext->sClient,             &#

76、160;                        pThis->m_hCOP, (DWORD_PTR)lpNewperHandleContext,                 

77、;                     0                             

78、60;        );                   if (NULL = hResult)                     

79、60;                         pThis->m_strLog.Format("關聯(lián)完成端口到客戶套接字失敗:%d", GetLastError();             &#

80、160;              Log(pThis->m_strLog);                             shutdown(lpPerIoContext-

81、>sClient, SD_BOTH);                            closesocket(lpPerIoContext->sClient);            

82、60;               lpPerIoContext->pNext = NULL;                            lpNewperHandleCon

83、text->pNext = NULL;              pThis->InsertToLookaside(lpPerIoContext, NULL);                         

84、0;  pThis->InsertToLookaside(NULL, lpNewperHandleContext);                            pThis->DecreaseClientNum();                                   

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論