封装了IOCP

1. 不使用线程池
2.  暂时只封装了 win32 的 icop
3.  暂时还未写测试用例,因为不知道怎么写 -_-!!!

//  networksocket.h: interface for the CNetworkSocket class.
//
/**/ //////////////////////////////////////////////////////////////////////

#if  !defined(NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_)
#define  NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_

#if  _MSC_VER > 1000
#pragma once
#endif   //  _MSC_VER > 1000

#include 
< vector >

#include 
< winsock2.h >
#include 
< process.h >
#pragma  comment(lib, 
" ws2_32.lib " )

#define  BUFFER_SIZE 4096

enum  OPERATION_TYPE
{
    OPERATION_TYPE_RECV 
= 0,
    OPERATION_TYPE_SEND 
= 1
}
;

// IO操作数据
typedef  struct  _PER_IO_OPERATION_DATA
{
    OVERLAPPED OverLapped;
    WSABUF DataBuf;
    
char szBuf[BUFFER_SIZE];
    OPERATION_TYPE OperationType;      
// 操作类型表示

}
PER_IO_OPERATION_DATA, * PPER_IO_OPERATION_DATA;

class  CNetworkSocket  
{
public:
    CNetworkSocket();
    
virtual ~CNetworkSocket();

    
bool init();
    
bool uninit();

    
bool initNetWork(unsigned short nPort);
    
bool unitNetWork();

    
bool send(SOCKET s, const char* pBuf, int nLen);

private:
    SOCKET m_listensock;
    HANDLE m_hIocpPort;
    std::vector
<HANDLE> m_vectorThreadHandle;

    
static unsigned __stdcall _WorkerThreadProc(void* pVoid);    
    
static unsigned __stdcall _AcceptThreadProc(void* pVoid);
}
;

#endif   //  !defined(NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_)

//  networksocket.cpp: implementation of the CNetworkSocket class.
//
/**/ //////////////////////////////////////////////////////////////////////

#include 
" networksocket.h "

/**/ //////////////////////////////////////////////////////////////////////
//  Construction/Destruction
/**/ //////////////////////////////////////////////////////////////////////

CNetworkSocket::CNetworkSocket()
{
    m_listensock 
= INVALID_SOCKET;
    m_hIocpPort  
= INVALID_HANDLE_VALUE;
}


CNetworkSocket::
~ CNetworkSocket()
{

}


bool  CNetworkSocket::init()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    
int nErrCode = 0;
    
    wVersionRequested 
= MAKEWORD(22);
    
    nErrCode 
= ::WSAStartup(wVersionRequested, &wsaData);
    
if ( nErrCode != 0 ) 
    
{
        
return false;
    }


    
if ( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) 
    
{
        
bool b = uninit();
        
return false;
    }

    
else
    
{
        
return true;
    }

}


bool  CNetworkSocket::uninit()
{
    
int nErrCode = 0;
    nErrCode 
= ::WSACleanup();

    
return true;
}


bool  CNetworkSocket::initNetWork(unsigned  short  nPort)
{
    
int nErrCode = 0;

    
// 创建 socket
    m_listensock = ::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
    
    
if( INVALID_SOCKET == m_listensock )
    
{
        nErrCode 
= ::WSAGetLastError();
        
return false;
    }


    
// 绑定端口
    sockaddr_in InternetAddr;
    InternetAddr.sin_family 
= AF_INET;
    InternetAddr.sin_addr.S_un.S_addr 
= ::htonl(INADDR_ANY);
    InternetAddr.sin_port 
= htons(nPort);

    
if( ::bind( m_listensock, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR )
    
{
        nErrCode 
= ::WSAGetLastError();
        
return false;
    }


    
// 开始监听
    if(    ::listen(m_listensock, 5== SOCKET_ERROR )
    
{
        nErrCode 
= ::WSAGetLastError();
        
return false;
    }


    
// 创建完成端口
    m_hIocpPort = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 00);
        
    
if( m_hIocpPort == INVALID_HANDLE_VALUE )
    
{
        nErrCode 
= ::WSAGetLastError();
        
return false;
    }


    
// 启动工作线程,线程数为CPU处理器数量*2+2
    SYSTEM_INFO sys_Info;
    ::GetSystemInfo(
&sys_Info);

    
for(int i = 0; i < (int(sys_Info.dwNumberOfProcessors) * 2 + 2); i++)
    
{
        HANDLE ThreadHandle 
= INVALID_HANDLE_VALUE;
        DWORD ThreadID      
= 0;
        
        unsigned 
int nThreadId  =   0 ;
        ThreadHandle 
= (HANDLE)_beginthreadex(NULL, 0, _WorkerThreadProc, (void *)this,  0&nThreadId);
        
        
if ( ThreadHandle == 0 )
            
return false;

        m_vectorThreadHandle.push_back(ThreadHandle);
    }


    
// 启动侦听线程
    HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
    unsigned 
int nThreadId = 0 ;

    ThreadHandle 
= (HANDLE)_beginthreadex(NULL, 0, _AcceptThreadProc, (void *)this,  0&nThreadId);
    
    
if ( ThreadHandle == 0 )
            
return false;

    m_vectorThreadHandle.push_back(ThreadHandle);

    
return true;
}


bool  CNetworkSocket::unitNetWork()
{
    
// 启动工作线程,线程数为CPU处理器数量*2+2
    SYSTEM_INFO sys_Info;
    ::GetSystemInfo(
&sys_Info);
    
    
for(int i = 0; i < (int(sys_Info.dwNumberOfProcessors) * 2 + 2); i++)
    
{
        
//寄出退出消息
        ::PostQueuedCompletionStatus(m_hIocpPort,    -1,    -1, NULL);
    }


    std::vector
<HANDLE>::iterator iter_t;
    
for ( iter_t = m_vectorThreadHandle.begin(); iter_t != m_vectorThreadHandle.end(); iter_t++ )
    

        DWORD dwRet 
= ::WaitForSingleObject(*iter_t, INFINITE);
    }


    
//关闭网络的侦听
    ::shutdown(m_listensock, 0);
    ::closesocket(m_listensock);
    
    
return true;
}


unsigned __stdcall CNetworkSocket::_WorkerThreadProc(
void *  pVoid)
{
    CNetworkSocket
* pThis = (CNetworkSocket*)pVoid;
    DWORD dwByteTransferred 
= 0;
    unsigned 
long nFlag = 0;
    DWORD RecvByte 
= 0;

    SOCKET ClientSock 
= INVALID_SOCKET;
     PPER_IO_OPERATION_DATA PerIoData;

     
while ( true )
     
{
        BOOL bSuccess 
= ::GetQueuedCompletionStatus(pThis->m_hIocpPort,
                                                       
&dwByteTransferred,
                                                     (LPDWORD)
&ClientSock,
                                                     (LPOVERLAPPED
*)&PerIoData,
                                                     INFINITE);

        
//退出信号到达,退出线程
        if( dwByteTransferred == -1 && PerIoData == NULL )
            
return 1;

        
//客户机已经断开连接或者连接出现错误
        if( dwByteTransferred == 0 && (PerIoData->OperationType == OPERATION_TYPE_RECV || PerIoData->OperationType == OPERATION_TYPE_SEND ) )
        
{
            ::closesocket(ClientSock);
            ::GlobalFree(PerIoData);
            
continue;
        }


        
// 接收完成
        if ( PerIoData->OperationType == OPERATION_TYPE_RECV )
        
{
            
// 处理接收数据
            
// pThis->OnRecv(ClientSock, PerIoData->szBuf, dwByteTransferred);

            
//将源数据置空
            ::memset(PerIoData->szBuf, 0, BUFFER_SIZE);
            dwByteTransferred
=0;

            
//重置IO操作数据
            unsigned long Flag=0;
            ::ZeroMemory(
&(PerIoData->OverLapped), sizeof(OVERLAPPED));
            
            PerIoData
->DataBuf.buf    = PerIoData->szBuf;
            PerIoData
->DataBuf.len    = BUFFER_SIZE;
            PerIoData
->OperationType = OPERATION_TYPE_RECV;

            
// 再投递另一个Recv请求
            ::WSARecv(ClientSock, &(PerIoData->DataBuf), 1&RecvByte, &Flag, &(PerIoData->OverLapped),    NULL);
        }


        
// 发送完成,置空缓冲区,释放缓冲区
        if( PerIoData->OperationType == OPERATION_TYPE_SEND )
        
{
            ::memset(PerIoData, 
0sizeof(PER_IO_OPERATION_DATA));
            ::GlobalFree(PerIoData);
            dwByteTransferred 
= 0;
        }

 
     }
// while ( true )

    
return 0;
}


unsigned __stdcall CNetworkSocket::_AcceptThreadProc(
void *  pVoid)
{
    CNetworkSocket
* pThis = (CNetworkSocket*)pVoid;

    SOCKET AcceptSock 
= INVALID_SOCKET;

    
while ( true )
    
{
        AcceptSock 
= ::WSAAccept(pThis->m_listensock, NULL, NULL, NULL, 0);

        
//关联客户端口到完成端口,句柄数据在此时被绑定到完成端口
        ::CreateIoCompletionPort((HANDLE)AcceptSock, pThis->m_hIocpPort, (DWORD)AcceptSock, 0);

        PPER_IO_OPERATION_DATA PerIoData 
= (PPER_IO_OPERATION_DATA)::GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
        unsigned 
long nFlag = 0;
        DWORD RecvByte 
= 0;
        ::ZeroMemory(
&(PerIoData->OverLapped),sizeof(OVERLAPPED));
        
        PerIoData
->DataBuf.buf     = PerIoData->szBuf;
        PerIoData
->DataBuf.len     = BUFFER_SIZE;
        PerIoData
->OperationType  = OPERATION_TYPE_RECV;

        
//提交首个接收数据请求
        
//这时
        
//如果客户端断开连接
        
//则也可以以接收数据时得到通知    
        ::WSARecv(AcceptSock, &(PerIoData->DataBuf), 1&RecvByte, &nFlag, &(PerIoData->OverLapped), NULL);

    }
// while ( true )

    
return 0;
}


bool  CNetworkSocket::send(SOCKET s,  const   char *  pBuf,  int  nLen)
{
    
if( s == INVALID_SOCKET || pBuf == NULL || nLen == 0 )
        
return false;
    
    PPER_IO_OPERATION_DATA PerIoData 
= (PPER_IO_OPERATION_DATA)::GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
    
    unsigned 
long nFlag = 0;
    DWORD dwSendByte 
= 0;
    ::ZeroMemory(
&(PerIoData->OverLapped), sizeof(OVERLAPPED));
    ::memcpy(PerIoData
->szBuf, pBuf, nLen);

    PerIoData
->DataBuf.buf = PerIoData->szBuf;
    PerIoData
->DataBuf.len = nLen;
    PerIoData
->OperationType  = OPERATION_TYPE_SEND;

    
int nRet = ::WSASend(s, &(PerIoData->DataBuf), 1&dwSendByte, nFlag, &(PerIoData->OverLapped), NULL);

    
if( nRet==SOCKET_ERROR && GetLastError() != WSA_IO_PENDING )
    
{
        
return false;
    }

    
else
    
{
        
return true;
    }

}

你可能感兴趣的:(封装了IOCP)