65.9K
CodeProject is changing. Read more.
Home

I/O Completion Port DLL

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.67/5 (9 votes)

Jul 21, 2008

CPOL

1 min read

viewsIcon

37190

downloadIcon

2812

This article explores the IO Completion Port mechanism provided in Windows and compare it with the other mechanisms available to wait for an IO completion

Introduction

The purpose of this article is to explore the IO Completion Port mechanism provided in Windows and compare it with the other mechanisms available to wait for an IO completion.

Large-scale software often needs tens of thousands of socket connections, and if one socket corresponds to one thread, meaning the thread costs the system great expense, IOCP presents an efficient solution to the "one-thread-per-client" bottleneck problem (among others), using only a few processing threads and asynchronous input/output send/receive. The IOCP technology is widely used for different types of high performance servers, such as Apache etc. The lssIocp.dll was something I maintained for two years (IOCP’s storehouse), and I hope my contribution can help somebody.

Background

This is my first article. My English is not very good, but I hoped to obtain everybody's encouragement. Three year’s ago, I needed a high performance server that could maintain 5000 connections at least, and the IOCP was the best solution. I wrote the lssIocp.dll with the help of the Code Project, and now I hope that everybody helps me to further consummate it.

Using the Code

To use lssIocp.dll, you need to include iocpdef.h to your project, and add a function named InitIocp

//int the header file Add:        SOCKET                         m_ListenSocket;
        HMODULE                        m_ModuleIocp;
        lpIocpNetInit                  m_pIocpNetInit;
        lpIocpNetListen                m_pIocpNetListen;
        lpIocpNetSend                  m_pIocpNetSend;
        lpIocpNetRelase                m_pIocpNetRelase;
        lpIocpNetCloseSocket           m_pIocpNetCloseSocket;
        lpIocpNetGetStringName         m_pIocpNetGetPeerName;        
}
CYhTSServerDoc::CYhTSServerDoc()
{
        // TODO: add one-time construction code here
        m_ModuleIocp=NULL;
        m_bListen=false;
        m_nListenPort=6000;
        
        m_pIocpNetInit=NULL;
        m_pIocpNetCloseSocket=NULL;
        m_pIocpNetGetPeerName=NULL;
        m_pIocpNetListen=NULL;
        m_pIocpNetRelase=NULL;
        m_pIocpNetSend=NULL;
}BOOL CYhTSServerDoc::InitIocp()
{
        m_ModuleIocp=AfxLoadLibrary(m_strPath+"\\lssIocp.dll");
        if(!m_ModuleIocp)
        {
               AfxMessageBox("lssIocp.dll loader failed");
               return FALSE;
        }
        m_pIocpNetInit         =(lpIocpNetInit)            GetProcAddress(m_ModuleIocp,
                                                           "IocpNetInit");
        m_pIocpNetListen       =(lpIocpNetListen)          GetProcAddress(m_ModuleIocp,
                                                           "IocpNetListen");
        m_pIocpNetSend         =(lpIocpNetSend)            GetProcAddress(m_ModuleIocp,
                                                           "IocpNetSend");
        m_pIocpNetRelase       =(lpIocpNetRelase)          GetProcAddress(m_ModuleIocp,
                                                           "IocpNetRelase");
        m_pIocpNetCloseSocket  =(lpIocpNetCloseSocket)     GetProcAddress(m_ModuleIocp,
                                                           "IocpNetCloseSocket");
        m_pIocpNetGetPeerName  =(lpIocpNetGetStringName)   GetProcAddress(m_ModuleIocp,
                                                           "IocpNetGetStringName");
        if(m_pIocpNetInit==NULL||m_pIocpNetListen==NULL||m_pIocpNetSend==NULL||\
                m_pIocpNetRelase==NULL||m_pIocpNetCloseSocket==NULL||
                m_pIocpNetGetPeerName==NULL)   
        {
               FreeLibrary(m_ModuleIocp);
               m_ModuleIocp=NULL;
               AfxMessageBox("init lssIocp.dll failed");
               return FALSE;
               
        }
        return TRUE;
}int WINAPI NetIocpCallback(IOCP_NET_INFO *pIocp)
{
        if(!pIocp)
               return 1;
        CYhTSServerDoc *pDoc=(CYhTSServerDoc*)pIocp->pOwner;
        if(!pDoc)
               return 1;
        switch(pIocp->cRetType)
        {
        case IOCP_RET_ACCEPT:          
               pDoc->OnAccept(pIocp->sParent,pIocp->sClient);
               break;
        case IOCP_RET_CLOSE:
               pDoc->OnClose(pIocp->sParent,pIocp->sClient);
               break;
        case IOCP_RET_RECEIVE: 
               pDoc->OnReceive(pIocp->sParent,pIocp->sClient,pIocp->pData,pIocp->nLen);
               break;
        default:
               break;
        }
        return 0;
        
}void CYhTSServerDoc::OnCloseDocument() 
{
        // TODO: Add your specialized code here and/or call the base class
        if(m_ModuleIocp)
        {
               m_pIocpNetRelase();
               FreeLibrary(m_ModuleIocp);
               m_ModuleIocp=NULL;
               
        }
        m_pIocpNetInit=NULL;
        m_pIocpNetCloseSocket=NULL;
        m_pIocpNetGetPeerName=NULL;
        m_pIocpNetListen=NULL;
        m_pIocpNetRelase=NULL;
        m_pIocpNetSend=NULL;
        CDocument::OnCloseDocument();
}