IOCP局域網監控研究論文

時間:2022-03-12 09:51:00

導語:IOCP局域網監控研究論文一文來源于網友上傳,不代表本站觀點,若需要原創文章可咨詢客服老師,歡迎參考。

IOCP局域網監控研究論文

摘要本文介紹了一種在WINDOWS平臺上比較成熟的I/O方法---完成端口,提出了通過使用iocp機制和旁視列表技術建立網絡服務器模型的方法,實現了利用為數不多的線程為成千上萬的客戶同時提供網絡服務,解決了大多數網絡服務器連接大量客戶端和處理大量數據時存在的問題,獲得了極好的性能和強大的擴展能力。文章給出了基于Windows2000平臺的局域網監控系統中網絡服務器的設計與實現過程。

關鍵詞完成端口;旁視列表;網絡服務器;VC++

1引言

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

2IOCP機制

IOCP(I/OCompletionPort輸入/輸出完成端口)是一種能夠合理利用與管理多線程的機制。該機制使用完成端口,用一定數量的線程處理重疊I/O(OverlappedI/O)的技術,幫助處理大量客戶端請求的網絡服務問題,特別適合于開發網絡服務器一類的應用程序,并可使系統的性能達到較佳狀態。IOCP模型圖如圖1所示。

圖1完成端口工作模式

完成端口模式要求創建一個Win32完成端口對象來對重疊I/O請求進行管理,并通過創建一定數量的工作者線程(WorkThread),來為已經完成的重疊I/O請求提供服務。其實,可以把完成端口看成系統維護的一個隊列,操作系統把重疊I/O操作完成的事件通知放入該隊列,由于是“操作完成”的事件通知,故取名為“完成端口”。一個完成端口被創建以后,可以和多個文件句柄進行關聯(文件句柄可以是真正的文件句柄,也可以是Socket句柄或命名管道),并在關聯后的句柄上進行重疊I/O操作。當I/O操作完成后,一個重疊I/O完成的事件通知就會被排在此端口的完成隊列上,此時,某個工作者線程將會被喚醒來為完成端口服務,執行特定的處理工作。一般來說,一個應用程序可以創建多個工作者線程來處理完成端口上的通知事件,工作者線程的數量依賴于程序的具體需要。

3數據庫同步機制實現過程:

(系統結構圖如圖2)

圖2系統結構圖

(1)整體系統安裝初始,各個同步端的數據庫初始化為一致。

(2)數據服務器維護各個同步端的SQL隊列,不斷檢查是否有操作項,然后將各項操作依序發送至各個在線的同步端。

(3)在線同步端收到后,置入SQL隊列,將SQL隊列按操作發生時間先后排序

(4)在線同步端將SQL隊列中的各項操作依序執行并通知服務器執行的結果。服務器收到后將該項操作從該同步端的SQL隊列中刪除。

(5)某一在線同步端執行非讀的SQL操作后,向服務器發送該操作,服務器將該操作放入除了此同步端外的其他同步端的SQL隊列中,并放入歷史SQL文件,然后轉到第2步

(6)有新同步端注冊入系統后,將從數據服務器(數據服務器同時建立該同步端的SQL隊列)下載歷史SQL文件,并執行其中各項操作。

(7)某同步端選擇注銷,數據服務器刪除該同步端的SQL隊列。

4內存分配機制

在該系統中內存的分配和釋放比較頻繁,為了比較高效分配釋放數據,采用一種稱作LookasideList(旁視列表)的數據結構。在該系統中用于單句柄數據和重疊操作數據(完成鍵)的分配和釋放。LookasideList的原理是在分配一塊數據空間前,先查看回收鏈表中是否有數據空間指針,如果有則不需要調用系統的內存分配,直接使用回收鏈表中的該指針指向的數據空間,并將回收鏈表中該指針節點移除,當使用完數據空間后,也不必調系統的內存釋放,而將該數據空間指針移入回收鏈表。在進程最終結束后才將回收鏈表中的所有指針指向的數據空間釋放。從而大大減低程序在運行期的頻繁內存分配和釋放產生的開銷。

5實現過程

5.1初始化

讀取服務器配置文件,初始化客戶端連接鏈表;建立完成端口,根據CPU個數建立等待和接受完成通知的線程;初始化WinSock接口,建立偵聽SOCKET;取擴展函數AcceptEx;關聯完成端口到偵聽SOCKET;綁定和偵聽。

5.2啟動服務

(1)建立網絡事件、設置該網絡事件為偵聽SOCKET的ACCEPT網絡事件,這樣當AcceptEx一次性分配的N個預備SOCKET由于滿足不斷上來的TCP連接而耗盡,并有新的TCP連接請求時,就會觸發偵聽SOCKET的ACCEPT事件,服務器就會在這個時機調用AcceptEx再次分配N個新的預備SOCKET以滿足新的TCP連接請求。在該系統中,N=10。

(2)分配的N個預備SOCKET

(3)建立檢查和分配線程,該線程作用:等待ACCEPT網絡事件以分配新的預備SOCKET;定時檢測和掛斷未收發任何數據且超時連接的TCP連接,防止DoS(拒絕服務)攻擊。

5.3完成通知線程內部處理

while(TRUE)

{

//等待完成端口的通知

bSuccess=GetQueuedCompletionStatus(

pThis->m_hCOP,

&dwNumberBytes,

(PULONG_PTR)&lpHandleContext,

&lpOverlapped,

INFINITE

);

if(!bSuccess)

{

pThis->m_strLog.Format("GetQueuedCompletionStatus()失敗:%d",GetLastError());

Log(pThis->m_strLog);

PPER_IO_CONTEXTlpPerIoContext=(PPER_IO_CONTEXT)lpOverlapped;

lpPerIoContext->pNext=NULL;

pThis->InsertToLookaside(lpPerIoContext,NULL);

lpHandleContext->pNext=NULL;

pThis->InsertToLookaside(NULL,lpHandleContext);

continue;

}

//如果外部發送空的單句柄數據指針,則退出完成通知線程

if(NULL==lpHandleContext)

{

return0;

}

//將完成鍵轉換為自己格式的數據指針

PPER_IO_CONTEXTlpPerIoContext=(PPER_IO_CONTEXT)lpOverlapped;

//這種情況表示客戶端自己掛斷連接

if(IoAccept!=lpPerIoContext->IoOperation)

{

if(0==dwNumberBytes)

{

shutdown(lpPerIoContext->sClient,SD_BOTH);

closesocket(lpPerIoContext->sClient);

lpPerIoContext->pNext=NULL;

pThis->InsertToLookaside(lpPerIoContext,NULL);

lpHandleContext->pNext=NULL;

pThis->InsertToLookaside(NULL,lpHandleContext);

pThis->DecreaseClientNum();

continue;

}

}

HANDLEhResult;

PPER_HANDLE_CONTEXTlpNewperHandleContext;

//判斷該通知為哪種類型的操作的結果

switch(lpPerIoContext->IoOperation)

{

//接受新的TCP連接

caseIoAccept:

pThis->IncreaseClientNum();

EnterCriticalSection(&pThis->m_ListCriSection);

pThis->ReleaseConnectionNode

(lpPerIoContext);

LeaveCriticalSection(&pThis->m_ListCriSection);

//將偵聽SOCKET的屬性復制給客戶端SOCKET,因為accept創建的socket會自動繼承偵聽socket的屬性,而AcceptEx不會

nResult=setsockopt(

lpPerIoContext->sClient,

SOL_SOCKET,

SO_UPDATE_ACCEPT_CONTEXT,

(char*)&pThis->m_ListenSocket,

sizeof(pThis->m_ListenSocket)

);

if(SOCKET_ERROR==nResult)

{

pThis->m_strLog.Format("客戶(ID=%d)SO_UPDATE_ACCEPT_CONTEXT失敗:%d",

lpPerIoContext->unId,WSAGetLastError());

Log(pThis->m_strLog);

closesocket(lpPerIoContext->sClient);

lpPerIoContext->pNext=NULL;

pThis->InsertToLookaside(lpPerIoContext,NULL);

pThis->DecreaseClientNum();

continue;

}

//為新的SOCKET分配單句柄數據

lpNewperHandleContext=pThis->GetHandleFromLookaside();

if(NULL==lpNewperHandleContext)

{

lpNewperHandleContext=(PPER_HANDLE_CONTEXT)HeapAlloc(

GetProcessHeap(),

HEAP_ZERO_MEMORY,

sizeof(PER_HANDLE_CONTEXT)

);

if(NULL==lpNewperHandleContext)

{

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

Log(pThis->m_strLog);

shutdown(lpPerIoContext->sClient,SD_BOTH);

closesocket(lpPerIoContext->sClient);

lpPerIoContext->pNext=NULL;

pThis->InsertToLookaside(lpPerIoContext,NULL);

pThis->DecreaseClientNum();

continue;

}

}

//將新的SOCKET關聯到同一完成端口上

lpNewperHandleContext->IoSocket=lpPerIoContext->sClient;

lpNewperHandleContext->pNext=NULL;

hResult=CreateIoCompletionPort(

(HANDLE)lpPerIoContext->sClient,\

pThis->m_hCOP,

(DWORD_PTR)lpNewperHandleContext,

);

if(NULL==hResult)

{

pThis->m_strLog.Format("關聯完成端口到客戶套接字失敗:%d",GetLastError());

Log(pThis->m_strLog);

shutdown(lpPerIoContext->sClient,SD_BOTH);

closesocket(lpPerIoContext->sClient);

lpPerIoContext->pNext=NULL;

lpNewperHandleContext->pNext=NULL;

pThis->InsertToLookaside(lpPerIoContext,NULL);

pThis->InsertToLookaside(NULL,lpNewperHandleContext);

pThis->DecreaseClientNum();

continue;

}

//接收來自CLIENT的數據

if(pThis->HandleData(lpPerIoContext,IO_READ_COMPLETION,dwNumberBytes))

pThis->DataAction(lpPerIoContext,lpNewperHandleContext);

continue;

//數據接收完的通知

caseIoRead:

if(pThis->HandleData(lpPerIoContext,IO_READ_COMPLETION,dwNumberBytes))

pThis->DataAction(lpPerIoContext,lpNewperHandleContext);

continue;

//數據發送完的通知

caseIoWrite:

if(pThis->HandleData(lpPerIoContext,IO_WRITE_COMPLETION,dwNumberBytes))

pThis->DataAction(lpPerIoContext,lpNewperHandleContext);

continue;

default:

continue;

}

}

數據處理都放在HandleData中實現,數據處理完后的響應代碼都在DataAction中實現,在此不做詳細介紹。

6結束語

編寫網絡服務器應用程序的難點在于程序的“可擴展性”,即如何開發出大容量且能處理大量并發SocketI/O請求的高性能應用程序。IOCP機制通過完成端口對象來對重疊I/O請求進行管理,并且利用多線程來處理重疊I/O操作完成后得到的數據,是一種與Win32Sockets結合度較高的實現高效率I/O的有效方法。

本文設計的網絡服務器在局域網監控系統中成功使用。實際應用表明:利用IOCP機制實現的網絡服務器應用程序能夠針對大量的客戶請求進行高效處理,在速度和性能上體現出其良好的特征,不失為一種實現網絡服務器的有效技術。

參考文獻

[1]張靜華,張玉明.IOCP研究及在大規模網絡通信系統中的應用.計算機與現代化,2004,9

[2]陳和平,周靜寧等.IOCP機制與網絡服務器實現方法.計算機應用,2003,4

[3]AnthonyJones,JimOhlund著.Windows網絡編程技術.機械工業出版社,2000,(176-206)

[4]潘愛民,王國印譯.VisualC++技術內幕(第四版).清華大學出版社,1999

[5]官章全,韓云君等.VisualC++6.0高級編程范例.電子工業出版社,2001