C++實例:封裝WSAEventSelect模型

字號:

#include
    #include
    #pragma comment(lib,"ws2_32.lib")
    #pragma once
    class CAsyncHandler
    {
    public:
    CAsyncHandler()
    {
    }
    virtual ~CAsyncHandler()
    {
    }
    virtual int AcceptNotify( SOCKET hSocket, const char *strClientIP, unsigned short usClientPort )= 0;
    };
    class CAsynch_Event_Handler
    {
    public:
    CAsynch_Event_Handler(void);
    ~CAsynch_Event_Handler(void);
    int Start(CAsyncHandler * phEvent, UINT unPort);
    int Stop(void);
    protected:
    static unsigned int __stdcall AcceptThread(void * lpParam);
    unsigned int AcceptThreadProc();
    private:
    SOCKET m_hListenSocket;
    HANDLE m_hIOThread;
    HANDLE m_hExitThread;
    CAsyncHandler *m_pEventHandler;
    private:
    int OnAccept();
    BOOL InitSocket()
    {
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD( 2, 2 );
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 )
    {
    /* Tell the user that we could not find a usable */
    /* WinSock DLL.
    */
    return FALSE;
    }
    /* Confirm that the WinSock DLL supports 2.2.*/
    /* Note that if the DLL supports versions greater */
    /* than 2.2 in addition to 2.2, it will still return */
    /* 2.2 in wVersion since that is the version we */
    /* requested. */
    if ( LOBYTE( wsaData.wVersion ) != 2 ||
    HIBYTE( wsaData.wVersion ) != 2 )
    {
    /* Tell the user that we could not find a usable */
    /* WinSock DLL. */
    WSACleanup( );
    return FALSE;
    }
    return TRUE;
    };
    BOOL ClearSocket()
    {
    WSACleanup( );
    return TRUE;
    };
    };
    ///*************** CPP*****************//
    #include "StdAfx.h"
    #include "Asynch_Event_Handler.h"
    #include
    using namespace std;
    CAsynch_Event_Handler::CAsynch_Event_Handler(void)
    {
    m_hListenSocket = INVALID_SOCKET;
    }
    CAsynch_Event_Handler::~CAsynch_Event_Handler(void)
    {
    }
    int CAsynch_Event_Handler::Start(CAsyncHandler * phEvent, UINT unPort)
    {
    if( m_hListenSocket != INVALID_SOCKET )
    {
    return 0;
    }
    InitSocket();
    m_pEventHandler = phEvent;
    struct sockaddr_in serverAddress;
    int err;
    m_hListenSocket = socket(AF_INET, SOCK_STREAM, 0);
    if( INVALID_SOCKET == m_hListenSocket )
    {
    err = WSAGetLastError();
    return err;
    }
    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = 0;
    serverAddress.sin_port = htons( unPort );
    err = bind(m_hListenSocket,
    (struct sockaddr *)&serverAddress,
    sizeof(serverAddress)
    );
    if( err == SOCKET_ERROR )
    {
    err = WSAGetLastError();
    closesocket( m_hListenSocket );
    m_hListenSocket = INVALID_SOCKET;
    return err;
    }
    err = listen( m_hListenSocket, SOMAXCONN );
    if( err == SOCKET_ERROR )
    {
    err = WSAGetLastError();
    closesocket( m_hListenSocket );
    m_hListenSocket = INVALID_SOCKET;
    return err;}
    m_hExitThread = CreateEvent( NULL, TRUE, FALSE, NULL );
    m_hIOThread = (HANDLE)
    _beginthreadex(
    NULL,
    0,
    AcceptThread,
    this,
    0,
    0 );
    return 0;
    }
    int CAsynch_Event_Handler::Stop(void)
    {
    if( INVALID_SOCKET == m_hListenSocket )
    {
    return 0;
    }
    closesocket( m_hListenSocket );
    m_hListenSocket = INVALID_SOCKET;
    SetEvent( m_hExitThread );
    if( WAIT_TIMEOUT == WaitForSingleObject( m_hIOThread, 10000 ) )
    {
    TerminateThread( m_hIOThread, 1 );
    }
    CloseHandle( m_hExitThread );
    CloseHandle( m_hIOThread );
    ClearSocket();
    return 0;
    }
    unsigned int CAsynch_Event_Handler::AcceptThreadProc()
    {
    WSANETWORKEVENTS Events;
    WSAEVENT hWaitAll[WSA_MAXIMUM_WAIT_EVENTS] = { INVALID_HANDLE_VALUE };
    hWaitAll[0] = m_hExitThread;
    hWaitAll[1] = WSACreateEvent();
    WSAEventSelect(
    m_hListenSocket,
    hWaitAll[1],
    FD_ACCEPT );
    int nWaitCounts = 2;
    while( TRUE )
    {
    DWORD wt = WSAWaitForMultipleEvents(
    nWaitCounts,
    hWaitAll,
    FALSE,
    INFINITE,
    TRUE );
    if( wt == WAIT_OBJECT_0 )
    {
    //退出線程
    break;
    }
    DWORD index = wt - WSA_WAIT_EVENT_0;
    if( index == 1 )
    {
    int nResult = WSAEnumNetworkEvents(
    m_hListenSocket,
    hWaitAll[1],
    &Events);
    if( 0 == nResult )
    {
    //接受
    if( Events.lNetworkEvents & FD_ACCEPT )
    {
    if( SOCKET_ERROR == Events.iErrorCode[FD_ACCEPT_BIT] )
    {
    continue;
    }
    else
    {
    //接受連接
    OnAccept();
    }
    }
    }
    }
    else if( wt == WAIT_IO_COMPLETION )
    {
    continue;
    }
    else
    {
    break;
    }
    }
    return 0;
    }
    unsigned int __stdcall CAsynch_Event_Handler::AcceptThread(void * lpParam)
    {
    CAsynch_Event_Handler *pAcceptor = (CAsynch_Event_Handler *)lpParam;
    return pAcceptor->AcceptThreadProc();
    }
    int CAsynch_Event_Handler::OnAccept()
    {
    SOCKET AcceptSocket;
    struct sockaddr_in clientAddress;
    int clientAddrLen = sizeof(sockaddr_in);
    AcceptSocket = accept( m_hListenSocket, (sockaddr *)&clientAddress, &clientAddrLen );
    if( INVALID_SOCKET == AcceptSocket )
    {
    return WSAGetLastError();
    }
    else
    {
    DWORD nValue = 1;
    int nLen = sizeof( nValue );
    if( SOCKET_ERROR == setsockopt( AcceptSocket, IPPROTO_TCP ,TCP_NODELAY, (char *)&nValue, nLen ) )
    {
    int err = WSAGetLastError();
    }
    nValue = 16384;
    if( SOCKET_ERROR == setsockopt( AcceptSocket, SOL_SOCKET ,SO_SNDBUF, (char *)&nValue, nLen ) )
    {
    int err = WSAGetLastError();
    }
    if( SOCKET_ERROR == setsockopt( AcceptSocket, SOL_SOCKET ,SO_RCVBUF, (char *)&nValue, nLen ) )
    {
    int err = WSAGetLastError();
    }
    m_pEventHandler->AcceptNotify( AcceptSocket, inet_ntoa( clientAddress.sin_addr ), ntohs( clientAddress.sin_port ) );
    return 0;
    }
    }