give me some better style advice, please

Started by
8 comments, last by EasySL 18 years ago

#ifndef __NetWork_H__
#define __NetWork_H__

#include <queue>

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

#include <MSWSock.h>

#include <windows.h>
#include <SocketErrorString.h>



//#define TRACE_CLOSESOCKET                       // &#36861;&#36394;&#36830;&#25509;&#20851;&#38381;
//#define TRACE_RECVSEND                          // &#36861;&#36394;&#25910;&#21457;&#25968;&#25454;



//////////////////////////////////////////////////////////////////////////

// &#32593;&#32476;&#28040;&#24687; &#28040;&#24687;&#22836; &#25152;&#26377;&#28040;&#24687;&#24517;&#39035;&#20174;&#36825;&#20010;&#32467;&#26500;&#27966;&#29983;

#define NET_PACKET_SIZE 255

#pragma pack( push )
#pragma pack( 1 )
struct NetPacket
{
    BYTE pakType;
    BYTE pakSize;
};
#pragma pack( pop )

//////////////////////////////////////////////////////////////////////////



// &#32593;&#32476;&#36830;&#25509;&#26631;&#35782;&#23383;&#31526;&#20018;&#65292;&#29992;&#26469;&#34920;&#31034;&#26576;&#20010;&#23458;&#25143;&#31471;&#36830;&#25509;&#26159;&#21542;&#26159;&#36825;&#20010;&#31243;&#24207;&#30340;&#23458;&#25143;&#31471;
extern char *NetWork_IdentifyString;



namespace NetWork 
{

    // &#32593;&#32476;&#20256;&#36755;&#21151;&#33021;&#21551;&#21160;
    bool Startup();

    // &#32593;&#32476;&#20256;&#36755;&#21151;&#33021;&#20851;&#38381;
    void Cleanup();

    // &#23436;&#25104;&#31471;&#21475;&#27599;&#25805;&#20316;&#32531;&#20914;&#21306;&#22823;&#23567;
    const DWORD IOCP_OVERLAPPED_BUFFER_LEN = 1024;



    // &#23436;&#25104;&#31471;&#21475;&#23436;&#25104;&#25805;&#20316;&#31867;&#22411;
    enum IOCP_OP            
    {
        IOP_ACCEPT,         // &#25509;&#21463;&#25805;&#20316;&#23436;&#25104;
        IOP_SEND,           // &#21457;&#36865;&#25805;&#20316;&#23436;&#25104;
        IOP_RECV,           // &#25509;&#25910;&#25805;&#20316;&#23436;&#25104;
        IOP_END,            // &#25509;&#21463;&#25805;&#20316;&#23436;&#25104;

        IOP_MAXOP
    };



    // &#23436;&#25104;&#24314;
    typedef struct tagCOMPLETIONKEY {
        SOCKET  s;
        void *  o;
    } COMPLETIONKEY, *LPCOMPLETIONKEY;



    // &#37325;&#21472;&#31471;&#21475;&#37325;&#21472;&#32467;&#26500;
    typedef struct tagIOCPOVERLAPPED {
        OVERLAPPED  o;
        SOCKET      s;
        SOCKET      sa;
        IOCP_OP     OP;
        char        buf[IOCP_OVERLAPPED_BUFFER_LEN];
        DWORD       len;
    } IOCPOVERLAPPED, *LPIOCPOVERLAPPED;




    // &#21551;&#21160;&#23436;&#25104;&#31471;&#21475;
    bool InitIOCP();

    // &#32467;&#26463;&#23436;&#25104;&#31471;&#21475;
    void TermIOCP();


    // &#23436;&#25104;&#31471;&#21475;&#21477;&#26564;

    extern HANDLE  hIoCompletionPort;


    // &#22788;&#29702;&#25509;&#21463;&#23436;&#25104;
    void     OnIoAccept  ( LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD& dwTrans );

    // &#22788;&#29702;&#21457;&#36865;&#23436;&#25104;
    void     OnIoSend    ( LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD& dwTrans );

    // &#22788;&#29702;&#25509;&#25910;&#23436;&#25104;
    void     OnIoRecv    ( LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD& dwTrans );

    // &#22788;&#29702;&#32467;&#26463;&#23436;&#25104;
    void     OnIoClose   ( LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD& dwTrans );


}



// IOCP &#32531;&#20914;&#21306;
class CIocpBuffer
{

public:

    CIocpBuffer( DWORD dwBufferSize );
    virtual ~CIocpBuffer();

    // &#21387;&#20837;&#25968;&#25454;
    void Push( char *pData, DWORD dwSize, bool &bSucceed );
    // &#24377;&#20986;&#25968;&#25454;
    void Pop( char *pData, DWORD &dwSize );

    void Lock();
    void Lock( char *&pData, DWORD &dwSize );
    void Unlock();

    void Empty();
    bool IsEmpty();

    // &#32531;&#20914;&#21306;&#22823;&#23567;
    DWORD m_dwBufferSize;
    // &#25968;&#25454;&#32531;&#20914;
    char *m_caData;
    // &#25968;&#25454;&#38271;&#24230;
    DWORD m_dwLength;
    // &#20851;&#38190;&#21306;
    CRITICAL_SECTION m_CRS;

};



// &#24120;&#37327;&#23450;&#20041;
static const int IOCPSOCKET_RECV_BUFFER_LEN  = 2048;        // &#25509;&#25910;&#32531;&#23384;&#22823;&#23567;
static const int IOCPSOCKET_SEND_BUFFER_LEN  = 1024;        // &#21457;&#36865;&#32531;&#20914;&#22823;&#23567;



// &#23436;&#25104;&#31471;&#21475;&#27169;&#22411;

class CSocketIoCompletionPort
{

public:

    // &#36830;&#25509;&#29366;&#24577;&#23450;&#20041;
    enum EnumSocketState
    {
        ESS_NULL,           // &#27809;&#26377;&#20934;&#22791;&#22909;

        ESS_READY,          // &#24050;&#32463;&#20934;&#22791;&#22909;&#65292;&#21487;&#20197;&#20351;&#29992;&#29366;&#24577;
        ESS_CLOSE,          // &#24050;&#32463;&#34987;&#20851;&#38381;

        ESS_MAX_STATE       // &#29366;&#24577;&#25968;&#37327;
    };


    // &#22788;&#29702;&#25509;&#21463;&#23436;&#25104;
    friend void     NetWork::OnIoAccept  ( NetWork::LPCOMPLETIONKEY pCK, NetWork::LPIOCPOVERLAPPED pOL, DWORD& dwTrans );

    // &#22788;&#29702;&#21457;&#36865;&#23436;&#25104;
    friend void     NetWork::OnIoSend    ( NetWork::LPCOMPLETIONKEY pCK, NetWork::LPIOCPOVERLAPPED pOL, DWORD& dwTrans );

    // &#22788;&#29702;&#25509;&#25910;&#23436;&#25104;
    friend void     NetWork::OnIoRecv    ( NetWork::LPCOMPLETIONKEY pCK, NetWork::LPIOCPOVERLAPPED pOL, DWORD& dwTrans );

    // &#22788;&#29702;&#32467;&#26463;&#23436;&#25104;
    friend void     NetWork::OnIoClose   ( NetWork::LPCOMPLETIONKEY pCK, NetWork::LPIOCPOVERLAPPED pOL, DWORD& dwTrans );

    CSocketIoCompletionPort();
    virtual ~CSocketIoCompletionPort();

public:

    void            MakeReady           ( VOID )                { mState = ESS_READY; }
    void            MakeClosed          ( VOID )                { mState = ESS_CLOSE; }

    bool            IsNotReady          ( VOID ) const          { return ESS_READY != mState; }
    bool            IsReady             ( VOID ) const          { return ESS_READY == mState; }
    bool            IsClosed            ( VOID ) const          { return ESS_CLOSE == mState; }

    // &#21019;&#24314;Socket
    virtual bool    Create              ( VOID );
    // &#37322;&#25918;Socket
    virtual void    Release             ( VOID );

    // &#24320;&#22987;&#30417;&#21548;
    virtual bool    Listen              ( u_short ushortPort );
    // &#36830;&#25509;&#26381;&#21153;&#22120;
    virtual bool    Connect             ( const char *szHostName, u_short ushortPort );
    // &#35774;&#32622;&#19968;&#20010;&#25509;&#21463;&#36827;&#26469;&#30340;&#36830;&#25509;
    void            StartAcceptSock     ( SOCKET sAccept );

    // &#21457;&#36865;&#25968;&#25454;&#21040;&#21457;&#36865;&#32531;&#20914;
    virtual bool    Send                ( void *pData, DWORD size );

    // &#20851;&#38381;socket
    void            CloseSocket         ( VOID );

protected:

    // &#24403;&#26377;&#19968;&#20010;&#36830;&#25509;&#36827;&#26469;&#26102;&#35843;&#29992;
    virtual CSocketIoCompletionPort*    
        OnAccept            ( VOID )                            { return new CSocketIoCompletionPort; }

    // &#24403;&#19968;&#20010;&#26032;&#36830;&#25509;&#24314;&#31435;&#23436;&#25104;
    virtual void    OnNewConnectDone    ( VOID )                {}
    // &#24403;&#26377;&#25968;&#25454;&#25509;&#25910;&#21040;&#26102;&#35843;&#29992;
    virtual void    OnReceve            ( NetPacket * pack )    { UNREFERENCED_PARAMETER(pack); }
    // &#24403;&#20851;&#38381;&#26102;&#34987;&#35843;&#29992;
    virtual void    OnClose             ( VOID )                {}

protected:

    // &#33719;&#21462;&#20027;&#26426;&#32593;&#32476;&#22320;&#22336;
    int             GetAddr             ( SOCKADDR_IN& addr, const char *szHostName, u_short ushortPort );
    // &#35774;&#32622;&#40664;&#35748;Socket&#36873;&#39033;
    void            SetDefaultOpt       ( SOCKET s );

    // &#21457;&#36865;&#36830;&#25509;&#26631;&#35782;&#31526;
    bool            SendIdentify        ( VOID );

    // &#25509;&#21463;&#19968;&#20010;&#36830;&#25509;
    void            AcceptSocket        ( SOCKET sAccept );

    // &#21457;&#20986;&#31532;&#19968;&#20010;&#25509;&#25910; Io command
    bool            StartRecv           ( HANDLE hIoCompletionPort );

    // &#21457;&#20986;&#19968;&#20010;&#25509;&#21463; Io command
    bool            PostAcceptEx        ( NetWork::LPIOCPOVERLAPPED lpCSSOverlapped );
    // &#21457;&#20986;&#19968;&#20010;&#21457;&#36865; Io command
    bool            PostSend            ( char *pData, DWORD dwSize );
    // &#21457;&#20986;&#19968;&#20010;&#25509;&#25910; Io command
    bool            PostRecv            ( NetWork::LPIOCPOVERLAPPED pCssOverlapped );

    // &#22788;&#29702;&#25509;&#25910;&#21040;&#30340;&#25968;&#25454;
    void            PushIn              ( char *pData, DWORD size );

protected:

    EnumSocketState             mState;                     // &#26159;&#21542;&#26377;&#25928;
    SOCKET                      m_Sock;                     // Socket &#21477;&#26564;
    HANDLE                      m_hEventCloseSocket;        // &#21487;&#20197;&#35843;&#29992;closesocket &#26469;&#20851;&#38381; &#36830;&#25509;&#30340;&#20107;&#20214;
    CIocpBuffer *               m_pIocpRecvBuffer;          // &#25509;&#25910;&#32531;&#20914;
    NetWork::LPCOMPLETIONKEY    m_pCompletionKey;           // &#23436;&#25104;&#24314;
    NetWork::LPIOCPOVERLAPPED   m_pRecvOverlapped;          // &#37325;&#21472;&#32467;&#26500;

};



typedef CSocketIoCompletionPort * ( *LPFN_NET_SERVER_NEWOBJECT ) ( VOID );
typedef void ( *LPFN_NET_CLIENT_ONRECV ) ( NetPacket * pack );


template <class T> CSocketIoCompletionPort * NetClientObject( VOID ) { return new T; }


namespace Net 
{
    namespace Server 
    {
        bool Start( USHORT port, LPFN_NET_SERVER_NEWOBJECT func );
        void Stop( VOID );
    }

    namespace Client 
    {
        bool Connect    ( LPCTSTR address, USHORT port, LPFN_NET_CLIENT_ONRECV func );
        void Disconnect ( VOID );
        bool Send       ( NetPacket * pack );
        bool IsClosed   ( VOID );
    }
}



#endif // __NetWork_H__



#include "stdafx.h"
#include <dbgnew.h>
#include <winsock2.h>
#include <windows.h>
#include <NetWork.h>




char *NetWork_IdentifyString = "Easideao NewWork Mask Information";



namespace NetWork
{

    bool Startup()
    {
        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; 
        }

        /* The WinSock DLL is acceptable. Proceed. */
        return true;
    }

    void Cleanup()
    {
        WSACleanup();
    }

    // &#23436;&#25104;&#31471;&#21475;&#21477;&#26564;

    HANDLE  hIoCompletionPort = INVALID_HANDLE_VALUE;


    // &#24037;&#20316;&#32447;&#31243;

    HANDLE  hWorkerThreads[MAXIMUM_WAIT_OBJECTS];
    DWORD   dwTotalWorkThread = 0;




    // IOCP &#24037;&#20316;&#32447;&#31243;

    DWORD WINAPI IOCPWorkerThread( PVOID pParam )
    {
        HANDLE  CP          = (HANDLE)pParam;
        DWORD   dwTrans;

        LPCOMPLETIONKEY     pCK;
        LPIOCPOVERLAPPED    pOL;

        for(;;)
        {
            // &#31561;&#24453;&#24182;&#33719;&#21462;&#23436;&#25104;&#31471;&#21475;&#20449;&#24687;
            BOOL rc = GetQueuedCompletionStatus( CP, &dwTrans, (PULONG_PTR)&pCK, (LPOVERLAPPED *)&pOL, INFINITE );
            DBG_UNREFERENCED_LOCAL_VARIABLE( rc );

            // &#23436;&#25104;&#20102;&#25152;&#26377;&#22788;&#29702;&#65292;&#25509;&#25910;&#21040;&#31243;&#24207;&#21457;&#20986;&#30340;&#32467;&#26463;&#32447;&#31243;&#65292;&#20174;&#27492;&#19981;&#33021;&#20877;&#32487;&#32493;&#25191;&#34892;&#20219;&#20309;&#31243;&#24207;
            if( (!pOL) && (!pCK) && (!dwTrans) )
                break;

            // &#20851;&#38381;&#19968;&#20010;&#36830;&#25509;
            if( !dwTrans )
            {
                switch( pOL->OP )
                {
                case IOP_RECV:
                case IOP_SEND:
                    // &#32467;&#26463;&#19968;&#20010;socket &#36830;&#25509;
                    OnIoClose( pCK, pOL, dwTrans );
                    break;
                }
                continue;
            }

            switch( pOL->OP )
            {
            case IOP_ACCEPT:
                OnIoAccept( pCK, pOL, dwTrans );
                break;

            case IOP_SEND:
                OnIoSend( pCK, pOL, dwTrans );
                break;

            case IOP_RECV:
                OnIoRecv( pCK, pOL, dwTrans );
                break;
            }
        }

        return 0;
    }




    bool InitIOCP()
    {
        // &#21019;&#24314;&#19968;&#20010;&#23436;&#25104;&#31471;&#21475;
        hIoCompletionPort = ::CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 );
        if( INVALID_HANDLE_VALUE == hIoCompletionPort )
        {
            LogErr( TEXT("CreateIoCompletionPort failed.") );
            return false;
        }

        // &#33719;&#24471;&#31995;&#32479;&#20449;&#24687;
        SYSTEM_INFO SystemInfo;
        GetSystemInfo( &SystemInfo );


        DWORD dwThreads = 1;
        // &#21019;&#24314;CPU*2+2&#20010;&#22788;&#29702;&#32447;&#31243;
        //dwThreads = SystemInfo.dwNumberOfProcessors * 2 + 2;

        for( DWORD i=0; i<dwThreads; i++ )
        {
            DWORD ThreadID;
            hWorkerThreads = ::CreateThread( NULL, 0, IOCPWorkerThread, hIoCompletionPort, 0, &ThreadID );
            dwTotalWorkThread ++;
        }

        Log( TEXT("Initialize Io Completion Port done.\n") );

        return true;
    }




    void TermIOCP()
    {
        DWORD i;

        Log( TEXT("Terminal IOCP WorkerThreads ... Starting\n") );

        // &#21457;&#20986;&#20572;&#27490; Io &#22788;&#29702;&#32447;&#31243;&#25351;&#20196;
        for ( i=0; i<dwTotalWorkThread; ++i ) {
            ::PostQueuedCompletionStatus( hIoCompletionPort, 0, (ULONG_PTR)0, 0 );
        }

        // &#31561;&#24453;&#25152;&#26377;&#32447;&#31243;&#32467;&#26463;
        DWORD r = ::WaitForMultipleObjects( dwTotalWorkThread, hWorkerThreads, TRUE, 15000 );
        switch( r )
        {
        case WAIT_TIMEOUT: 
            Log( TEXT("Not IOCP WorkerThreads dead in time!\n") ); 
            break;
        case WAIT_FAILED:  
            Log( TEXT("Kill IOCP WorkerThreads WaitForMultipleObjects WAIT_FAILED!\n") ); 
            break;
        default: 
            Log( TEXT("Terminal IOCP WorkerThreads ... done\n") );
            break;
        }

        // &#20851;&#38381;&#25152;&#26377;&#32447;&#31243;
        for( i=0; i<dwTotalWorkThread; i++ ) {
            ::CloseHandle( hWorkerThreads );
        }

        // &#20851;&#38381;&#23436;&#25104;&#31471;&#21475;
        ::CloseHandle( hIoCompletionPort );
    }



    //========================================================================

    // &#22788;&#29702;&#25509;&#21463;&#23436;&#25104;
    void OnIoAccept( LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD& dwTrans )
    {
        UNREFERENCED_PARAMETER( dwTrans );

        CSocketIoCompletionPort *pThis = (CSocketIoCompletionPort *)pCK->o;
        DWORD IdLen = (DWORD)strlen( NetWork_IdentifyString );

        // &#25509;&#21463;&#36830;&#25509;
        if( strncmp( pOL->buf, NetWork_IdentifyString, IdLen ) == 0 )
        {
            pThis->AcceptSocket( pOL->sa );
        }

        pThis->PostAcceptEx( pOL );
    }



    //========================================================================

    // &#22788;&#29702;&#21457;&#36865;&#23436;&#25104;
    void OnIoSend( LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD& dwTrans )
    {
        CSocketIoCompletionPort *pThis = (CSocketIoCompletionPort *)pCK->o;

        if( dwTrans < pOL->len )
        {
            pThis->MakeClosed();
            SetEvent( pThis->m_hEventCloseSocket );
        }

        delete pOL;
    }


    //========================================================================

    // &#22788;&#29702;&#25509;&#25910;&#23436;&#25104;
    void OnIoRecv( LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD& dwTrans )
    {
        CSocketIoCompletionPort *pThis = (CSocketIoCompletionPort *)pCK->o;

        // &#25509;&#25910;&#25968;&#25454;
        pThis->PushIn( pOL->buf, dwTrans );
        pThis->PostRecv( pOL );
    }



    //========================================================================

    // &#22788;&#29702;&#32467;&#26463;&#23436;&#25104;
    void OnIoClose( LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD& dwTrans )
    {
        UNREFERENCED_PARAMETER( dwTrans );
        UNREFERENCED_PARAMETER( pOL );

        CSocketIoCompletionPort *pThis = (CSocketIoCompletionPort *)pCK->o;
        pThis->MakeClosed();
        SetEvent( pThis->m_hEventCloseSocket );
    }



}



CIocpBuffer::CIocpBuffer( DWORD dwBufferSize )
{
    m_caData = new char [dwBufferSize];
    m_dwBufferSize = dwBufferSize;
    m_dwLength = 0;
    InitializeCriticalSection( &m_CRS );
}



//========================================================================

CIocpBuffer::~CIocpBuffer()
{
    DeleteCriticalSection( &m_CRS );
    delete [] m_caData;
}



//========================================================================

// &#21387;&#20837;&#25968;&#25454;
void CIocpBuffer::Push( char *pData, DWORD dwSize, bool &bSucceed )
{
    EnterCriticalSection( &m_CRS );

    bSucceed = false;

    if( dwSize > 0 && m_dwLength + dwSize <= m_dwBufferSize )
    {
        memcpy( &m_caData[m_dwLength], pData, dwSize );
        m_dwLength += dwSize;
        bSucceed = true;
    }

    LeaveCriticalSection( &m_CRS );
}



//========================================================================

// &#24377;&#20986;&#25968;&#25454;
void CIocpBuffer::Pop( char *pData, DWORD &dwSize )
{
    EnterCriticalSection( &m_CRS );

    dwSize = 0;

    if( m_dwLength > 0 )
    {
        if( pData )
            memcpy( pData, m_caData, m_dwLength );
        dwSize = m_dwLength;
        m_dwLength = 0;
    }

    LeaveCriticalSection( &m_CRS );
}



//========================================================================
void CIocpBuffer::Lock()
{
    EnterCriticalSection( &m_CRS );
}



//========================================================================

void CIocpBuffer::Lock( char *&pData, DWORD &dwSize )
{
    EnterCriticalSection( &m_CRS );
    pData = m_caData;
    dwSize = m_dwLength;
}



//========================================================================

void CIocpBuffer::Unlock()
{
    LeaveCriticalSection( &m_CRS );
}



//========================================================================

void CIocpBuffer::Empty()
{
    m_dwLength = 0;
}



//========================================================================

bool CIocpBuffer::IsEmpty()
{
    return (m_dwLength == 0);
}



GUID            GuidAcceptEx    = WSAID_ACCEPTEX;
LPFN_ACCEPTEX   lpfnAcceptEx    = NULL;


//////////////////////////////////////////////////////////////////////////








//========================================================================

CSocketIoCompletionPort::CSocketIoCompletionPort()
{
    m_Sock                  = INVALID_SOCKET;
    m_hEventCloseSocket     = INVALID_HANDLE_VALUE;

    mState                  = ESS_NULL;

    m_pIocpRecvBuffer       = new CIocpBuffer( IOCPSOCKET_RECV_BUFFER_LEN );

    m_pCompletionKey        = NULL;
    m_pRecvOverlapped       = NULL;
}



//========================================================================

CSocketIoCompletionPort::~CSocketIoCompletionPort()
{
    delete m_pIocpRecvBuffer;
}




//========================================================================

// &#21019;&#24314;Socket
bool CSocketIoCompletionPort::Create( )
{
    // &#21021;&#22987;&#21270;&#23436;&#25104;&#31471;&#21475;
    if( !NetWork::InitIOCP() )
    {
        LogErr( TEXT( "Initialize a IOCP Failed" ) );
        return false;
    }

    // &#21019;&#24314;&#19968;&#20010;Socket
    m_Sock = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );
    if( INVALID_SOCKET == m_Sock )
    {
        LogSockErr( TEXT("Create socket handle failed") );
        return false;
    }

    SetDefaultOpt( m_Sock );

    return true;
}



//========================================================================

// &#37322;&#25918;Socket
void CSocketIoCompletionPort::Release()
{
    CloseSocket();
}


//========================================================================

// &#24320;&#22987;&#30417;&#21548;
bool CSocketIoCompletionPort::Listen( u_short ushortPort )
{
    int err;

    // &#35774;&#32622;&#20027;&#26426;&#22320;&#22336;&#20449;&#24687;
    SOCKADDR_IN InternetAddr;
    int AddrSize = sizeof( SOCKADDR_IN );
    ZeroMemory( &InternetAddr, AddrSize );

    InternetAddr.sin_family         = AF_INET;
    InternetAddr.sin_addr.s_addr    = htonl( INADDR_ANY );
    InternetAddr.sin_port           = htons( ushortPort );

    // &#32465;&#23450;&#20027;&#26426;&#22320;&#22336;
    err = bind( m_Sock, (PSOCKADDR)&InternetAddr, AddrSize );
    if( err == SOCKET_ERROR )
    {
        LogSockErr( TEXT("Bind listen port failed") );
        return false;
    }

    // &#24320;&#22987;&#30417;&#21548;&#31471;&#21475;
    err = listen( m_Sock, 5 );
    if( err == SOCKET_ERROR )
    {
        LogSockErr( TEXT("Listen start failed") );
        return false;
    }

    // &#20851;&#32852;&#23436;&#25104;&#31471;&#21475;
    m_pCompletionKey = new NetWork::COMPLETIONKEY;
    m_pCompletionKey->s = m_Sock;
    m_pCompletionKey->o = this;
    CreateIoCompletionPort( (HANDLE)m_Sock, NetWork::hIoCompletionPort, (ULONG_PTR)m_pCompletionKey, 0 );

    // &#33719;&#24471;lpfnAcceptEx &#20989;&#25968;&#25351;&#38024;
    DWORD dwBytes;

    err = WSAIoctl( m_Sock, SIO_GET_EXTENSION_FUNCTION_POINTER
        , &GuidAcceptEx, sizeof(GuidAcceptEx)
        , &lpfnAcceptEx, sizeof(lpfnAcceptEx)
        , &dwBytes, NULL, NULL );
    if( err == SOCKET_ERROR )
    {
        LogSockErr( TEXT("Get lpfnAcceptEx failed") );
        return false;
    }

    m_pRecvOverlapped = new NetWork::IOCPOVERLAPPED;

    if( !PostAcceptEx( m_pRecvOverlapped ) )
    {
        Log( TEXT("PostAcceptEx Failed %s(%d)\n"), TEXT(__FILE__), __LINE__ );
        return false;
    }

    // &#36830;&#25509;&#23601;&#32490;
    MakeReady();

    return true;
}



//========================================================================

// &#36830;&#25509;&#21040;&#26381;&#21153;&#22120;
bool CSocketIoCompletionPort::Connect( const char *szHostName, u_short ushortPort )
{
    SOCKADDR_IN PeerAddr;
    int AddrLen = GetAddr( PeerAddr, szHostName, ushortPort );

    int err = WSAConnect( m_Sock, (SOCKADDR*)&PeerAddr, AddrLen, NULL, NULL, NULL, NULL );
    if( err )
    {
        LogSockErr( TEXT("WSAConnect call failed") );
        return false;
    }

    if( !SendIdentify() )
    {
        LogErr( TEXT("Connect send identify failed") );
        return false;
    }

    m_hEventCloseSocket = CreateEvent( NULL, TRUE, FALSE, NULL );

    // &#36830;&#25509;&#23601;&#32490;
    MakeReady();

    if( !StartRecv( NetWork::hIoCompletionPort ) )
    {
        LogErr( TEXT("Connect start recv net message failed") );
        return false;
    }

    return true;
}



//========================================================================

// &#35774;&#32622;&#19968;&#20010;&#25509;&#21463;&#36827;&#26469;&#30340;&#36830;&#25509;
void CSocketIoCompletionPort::StartAcceptSock( SOCKET sAccept )
{
    m_Sock = sAccept;

    SetDefaultOpt( m_Sock );

    m_hEventCloseSocket = CreateEvent( NULL, TRUE, FALSE, NULL );

    // &#36830;&#25509;&#23601;&#32490;
    MakeReady();
}



//========================================================================

// &#21457;&#36865;&#25968;&#25454;&#21040;&#21457;&#36865;&#32531;&#20914;
bool CSocketIoCompletionPort::Send( void *pData, DWORD size )
{
    if( IsReady() )
        return PostSend( (char *)pData, size );
    else    
        return false;
}



void CSocketIoCompletionPort::CloseSocket( VOID )
{
    OnClose();

#ifdef TRACE_CLOSESOCKET
    const int msgLen = 4096;
    TCHAR dbgMsg[msgLen];
    SafeFTS( dbgMsg, msgLen, TEXT( "Close socket [%d] starting." ), m_Sock );
    LogErr( dbgMsg );
#endif 

    ::closesocket( m_Sock );

    if( INVALID_HANDLE_VALUE != m_hEventCloseSocket )
    {
        DWORD r = WaitForSingleObject( m_hEventCloseSocket, 30000 );
        if( WAIT_OBJECT_0 == r )
        {
#ifdef TRACE_CLOSESOCKET
            SafeFTS( dbgMsg, msgLen, TEXT( "Close socket [%d] done." ), m_Sock );
            LogErr( dbgMsg );
#endif 
        }
        else
        {

#ifdef TRACE_CLOSESOCKET
            SafeFTS( dbgMsg, msgLen, TEXT( "Close socket [%d] failed." ), m_Sock );
            LogErr( dbgMsg );
#endif
        }
        CloseHandle( m_hEventCloseSocket );
    }
    m_Sock = INVALID_SOCKET;

    delete m_pCompletionKey;
    delete m_pRecvOverlapped;
}



//////////////////////////////////////////////////////////////////////////



//========================================================================

// &#33719;&#21462;&#20027;&#26426;&#32593;&#32476;&#22320;&#22336;
int CSocketIoCompletionPort::GetAddr( SOCKADDR_IN& addr, const char *szHostName, u_short ushortPort )
{
    int AddrLen = sizeof( SOCKADDR_IN );
    ZeroMemory( &addr, AddrLen );

    addr.sin_family         = AF_INET;
    addr.sin_port           = htons( ushortPort );
    addr.sin_addr.s_addr    = inet_addr( szHostName );

    if( addr.sin_addr.s_addr == INADDR_NONE )
    {
        HOSTENT * lphost = ::gethostbyname( szHostName );
        if( lphost == NULL )
            return false;

        addr.sin_addr.s_addr = ((IN_ADDR *)lphost->h_addr)->s_addr;
    }

    return AddrLen;
}



//========================================================================

// &#35774;&#32622;&#40664;&#35748;Socket&#36873;&#39033;
void CSocketIoCompletionPort::SetDefaultOpt( SOCKET s )
{
    // &#19981;&#25302;&#24310;&#35774;&#32622;
    BOOL bDontLinger;
    int DontLingerSize = sizeof(BOOL);
    getsockopt( m_Sock, SOL_SOCKET, SO_DONTLINGER, (char *)&bDontLinger, &DontLingerSize );

    bDontLinger = TRUE;
    setsockopt( m_Sock, SOL_SOCKET, SO_DONTLINGER, (char *)&bDontLinger, DontLingerSize );

    // &#35774;&#32622;&#25191;&#34892;closesocket&#26102;&#65292;&#22312;&#22871;&#25509;&#23383;&#19978;&#25490;&#38431;&#25968;&#25454;&#30340;&#36887;&#30041;&#26102;&#38388;
    struct linger l;
    int LingerSize = sizeof(linger); 
    getsockopt( m_Sock, SOL_SOCKET, SO_LINGER, (char *)&l, &LingerSize );

    // &#20445;&#25345;&#27963;&#21160;
    BOOL bKeepALife;
    int KeepALifeSize = sizeof(BOOL);
    getsockopt( m_Sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&bKeepALife, &KeepALifeSize );

    // &#31105;&#27490;Nagle &#31639;&#27861; &#24310;&#36831;&#21457;&#36865;&#25968;&#25454;
    int bNoDelay = TRUE;
    setsockopt( s, IPPROTO_TCP, TCP_NODELAY, (char*)&bNoDelay, sizeof(int));
}



//========================================================================

// &#21457;&#36865;&#36830;&#25509;&#26631;&#35782;&#31526;
bool CSocketIoCompletionPort::SendIdentify()
{
    // &#21457;&#36865;&#36830;&#25509;&#26631;&#35782;
    WSABUF wsaBuf;
    wsaBuf.buf = NetWork_IdentifyString;
    wsaBuf.len = (u_long)strlen( NetWork_IdentifyString );
    DWORD dwNumberOfBytesSent;

    int err = WSASend( m_Sock, &wsaBuf, 1, &dwNumberOfBytesSent, 0, 0, 0 );
    if( SOCKET_ERROR == err )
    {
        int e = WSAGetLastError();
        switch( e )
        {
        case WSA_IO_PENDING:
        case 0:
            break;
        default:
            LogSockErrCode( TEXT("Send identify string failed"), e );
            return false;
        }
    }

    return true;
}



//========================================================================

// &#25509;&#21463;&#19968;&#20010;&#36830;&#25509;
void CSocketIoCompletionPort::AcceptSocket( SOCKET sAccept )
{
    int rc = setsockopt( sAccept, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&m_Sock, sizeof(SOCKET) );
    if( rc == SOCKET_ERROR )
    {
        int e = WSAGetLastError();
        LogErr( GetSocketErrorString( e ) );
        closesocket( sAccept );
    }

    CSocketIoCompletionPort *pSock = OnAccept();

    pSock->StartAcceptSock( sAccept );

    pSock->StartRecv( NetWork::hIoCompletionPort );

    pSock->OnNewConnectDone();
}



//========================================================================

// &#21457;&#20986;&#31532;&#19968;&#20010;&#25509;&#25910; Io command
bool CSocketIoCompletionPort::StartRecv( HANDLE hIoCompletionPort )
{
    m_pCompletionKey = new NetWork::COMPLETIONKEY;
    m_pCompletionKey->s = m_Sock;
    m_pCompletionKey->o = this;

    HANDLE hrc = CreateIoCompletionPort( (HANDLE)m_Sock, hIoCompletionPort, (ULONG_PTR)m_pCompletionKey, 0 );
    if( hrc == NULL )
    {
        LogErr( TEXT("StartRecv Associate CompletionPort Failed\n") );
        return false;
    }

    m_pRecvOverlapped = new NetWork::IOCPOVERLAPPED;

    if( !PostRecv( m_pRecvOverlapped ) )
    {
#ifdef TRACE_RECVSEND
        LogErr( TEXT("CSocketService AcceptSocket Failed\n(%s:%d)") );
#endif
        MakeClosed();
        return false;
    }

    return true;
}



//========================================================================

// &#21457;&#20986;&#19968;&#20010;&#25509;&#21463; Io command
bool CSocketIoCompletionPort::PostAcceptEx( NetWork::LPIOCPOVERLAPPED lpCSSOverlapped )
{
    SOCKET sAccept = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );

    if( sAccept == INVALID_SOCKET )
    {
        int e = WSAGetLastError();
        LogErr( GetSocketErrorString( e ) );
        return false;
    }

    ZeroMemory( lpCSSOverlapped, sizeof(NetWork::IOCPOVERLAPPED) );
    lpCSSOverlapped->OP         = NetWork::IOP_ACCEPT;
    lpCSSOverlapped->s          = m_Sock;
    lpCSSOverlapped->sa         = sAccept;
    lpCSSOverlapped->len        = 1024;
    char *buffer    = lpCSSOverlapped->buf;
    int bufferlen   = lpCSSOverlapped->len;
    DWORD dwBytes;

    int err = lpfnAcceptEx( m_Sock
        , sAccept
        , buffer
        , bufferlen - ((sizeof(SOCKADDR_IN)+16)*2)
        , sizeof(SOCKADDR_IN)+16
        , sizeof(SOCKADDR_IN)+16
        , &dwBytes
        , &lpCSSOverlapped->o );

    if( err == SOCKET_ERROR )
    {
        int e = WSAGetLastError();
        if( e != WSA_IO_PENDING )
        {
            LogSockErrCode( TEXT("lpfnAcceptEx call failed"), e );
            return false;
        }
    }

    return true;
}



//========================================================================

// &#21457;&#20986;&#19968;&#20010;&#21457;&#36865; Io command
bool CSocketIoCompletionPort::PostSend( char *pData, DWORD dwSize )
{
    NetWork::LPIOCPOVERLAPPED pOverlapped = new NetWork::IOCPOVERLAPPED;
    ZeroMemory( pOverlapped, sizeof(NetWork::IOCPOVERLAPPED) );

    memcpy( pOverlapped->buf, pData, dwSize );

    pOverlapped->len        = dwSize;
    pOverlapped->OP         = NetWork::IOP_SEND;
    pOverlapped->s          = m_Sock;
    pOverlapped->sa         = INVALID_SOCKET;

    WSABUF wsaBuf;
    wsaBuf.buf = pOverlapped->buf;
    wsaBuf.len = pOverlapped->len;
    DWORD dwNumberOfBytesSent;

    //m_SendBuffer.In( pOverlapped );
    //Log( "WSASend Data[%d]\n", pOverlapped->len );
    int err = WSASend( m_Sock, &wsaBuf, 1, &dwNumberOfBytesSent, 0, &pOverlapped->o, NULL );
    if( err == SOCKET_ERROR )
    {
        int e = WSAGetLastError();
        if( e != WSA_IO_PENDING )
        {
#ifdef TRACE_RECVSEND
            LogSockErrCode( TEXT("Post send io command failed"), e );
#endif
            MakeClosed();
            return false;
        }
    }

    return true;
}



//========================================================================

// &#21457;&#20986;&#19968;&#20010;&#25509;&#25910; Io command
bool CSocketIoCompletionPort::PostRecv( NetWork::LPIOCPOVERLAPPED pCssOverlapped )
{
    if( IsNotReady() )
        return false;

    ZeroMemory( pCssOverlapped, sizeof(NetWork::IOCPOVERLAPPED) );
    pCssOverlapped->len         = 1024;
    pCssOverlapped->OP          = NetWork::IOP_RECV;
    pCssOverlapped->s           = m_Sock;
    pCssOverlapped->sa          = INVALID_SOCKET;

    static WSABUF wsaBuf;
    wsaBuf.buf = pCssOverlapped->buf;
    wsaBuf.len = pCssOverlapped->len;
    DWORD dwNumberOfBytesRecvd = 0;
    DWORD dwFlags = 0;

    int err = WSARecv( m_Sock, &wsaBuf, 1, &dwNumberOfBytesRecvd, &dwFlags, &pCssOverlapped->o, NULL );
    if( err == SOCKET_ERROR )
    {
        int e = WSAGetLastError();
        if( e != WSA_IO_PENDING )
        {
#ifdef TRACE_RECVSEND
            LogSockErrCode( TEXT("PostRecv :"), e );
#endif
            MakeClosed();
            return false;
        }
    }

    return true;
}



//========================================================================

// &#22788;&#29702;&#25509;&#25910;&#21040;&#30340;&#25968;&#25454;
void CSocketIoCompletionPort::PushIn( char *pData, DWORD size )
{
    if( IsNotReady() )
        return;

    m_pIocpRecvBuffer->Lock();

    char *&pBuffer = m_pIocpRecvBuffer->m_caData;
    DWORD &dwLen = m_pIocpRecvBuffer->m_dwLength;

    if( dwLen + size <= m_pIocpRecvBuffer->m_dwBufferSize )
    {
        memcpy( pBuffer, pData, size );
        dwLen += size;

        DWORD p = 0;
        DWORD len = 0;
        while( dwLen >= sizeof(NetPacket) )
        {
            NetPacket * pack = (NetPacket *)&pBuffer;
            len = pack->pakSize;
            if( dwLen >= len )
            {
                OnReceve( pack );
                p += len;
                dwLen -= len;
            } 
            else break;
        }

        if( dwLen > 0 )
        {
            memcpy( &pBuffer[0], &pBuffer, dwLen );
        }
    } 
    else 
        MakeClosed();

    m_pIocpRecvBuffer->Unlock();
}




//////////////////////////////////////////////////////////////////////////




typedef CSocketIoCompletionPort * ( *LPFN_NET_SERVER_NEWOBJECT ) ( VOID );
typedef void ( *LPFN_NET_CLIENT_ONRECV ) ( NetPacket * pack );


CSocketIoCompletionPort * DummyServerNewObject( VOID )
{
    return new CSocketIoCompletionPort;
}



void DummyClientOnRecv( NetPacket * pack )
{
    UNREFERENCED_PARAMETER( pack );
}


LPFN_NET_SERVER_NEWOBJECT   lpfn_Server_NewObject   = DummyServerNewObject;
LPFN_NET_CLIENT_ONRECV      lpfn_Client_OnRecv      = DummyClientOnRecv;



class CInternetGameServer : public CSocketIoCompletionPort
{
public:

    bool Create( u_short ushortPort )
    {
        if( !CSocketIoCompletionPort::Create() )
            return false;

        if( !Listen( ushortPort ) )
            return false;

        return true;
    }

    virtual void Release( VOID )
    {
        ::closesocket( m_Sock );
        NetWork::TermIOCP();
        m_Sock = INVALID_SOCKET;
        delete m_pCompletionKey;
        delete m_pRecvOverlapped;
    }

protected:

    virtual CSocketIoCompletionPort*    OnAccept    ( VOID ) { return lpfn_Server_NewObject(); }

};



class CInternetGameClient : public CSocketIoCompletionPort
{
public:

    virtual bool Connect( const char *szHostName, u_short ushortPort )
    {
        if( !CSocketIoCompletionPort::Create() )
            return false;

        if( !CSocketIoCompletionPort::Connect( szHostName, ushortPort ) )
            return false;

        return true;
    }

    virtual void Release()
    {
        CSocketIoCompletionPort::Release();

        NetWork::TermIOCP();
    }

    virtual void OnReceve( NetPacket * pack )
    {
        lpfn_Client_OnRecv( pack );
    }

};




namespace Net 
{



    CInternetGameServer * theGameServer = NULL;
    CInternetGameClient * theGameClient = NULL;
    


    namespace Server
    {



        bool Start( USHORT port, LPFN_NET_SERVER_NEWOBJECT func )
        {
            if( theGameServer )
                return false;

            if( !NetWork::Startup() )
            {
                Log( TEXT("network startup failed.\n") );
                return false;
            }

            lpfn_Server_NewObject = func;

            theGameServer = new CInternetGameServer;
            if( !theGameServer->Create( port ) )
            {
                Log( TEXT("start server falied on port [%d]\n"), port );
                return false;
            }

            return true;
        }


        void Stop( VOID )
        {
            if( theGameServer )
            {
                theGameServer->Release();
                delete theGameServer;
                theGameServer = NULL;
                NetWork::Cleanup();
            }
        }


    }


    namespace Client
    {



        bool Connect( LPCTSTR address, USHORT port, LPFN_NET_CLIENT_ONRECV func )
        {
            if( theGameClient )
                return false;
           
            if( !NetWork::Startup() )
            {
                Log( TEXT("network startup failed.\n") );
                return false;
            }

            lpfn_Client_OnRecv = func;

            theGameClient = new CInternetGameClient;

            char szAddress[1024];

#ifdef UNICODE
            WideCharToMultiByte( CP_ACP, 0, address, -1, szAddress, 1024, NULL, NULL );
#else 
            strcpy_s( szAddress, 1024, m_SetupInfo.szServerAddress );
#endif

            if( !theGameClient->Connect( szAddress, port ) )
            {
                LogErr( TEXT("Failed to connect Server!") );
                return false;
            }

            return true;
        }



        void Disconnect( VOID )
        {
            if( theGameClient )
            {
                theGameClient->Release();
                delete theGameClient;
                theGameClient = NULL;
                NetWork::Cleanup();
            }
        }



        bool Send( NetPacket * pack )
        {
            if( theGameClient )
                return theGameClient->Send( pack, pack->pakSize );

            return false;
        }



        bool IsClosed( VOID )
        {
            if( theGameClient )
                return theGameClient->IsClosed();
            return false;
        }



    }

 
}


[Edited by - Run_The_Shadows on April 2, 2006 12:19:56 PM]
Advertisement
Please use source tags. Your current post is unreadable.
Check the FAQ for how to use source tags.
Or edit my post to see how I do this:
if (true) {    std::cout << "It works";}


Regards,
/Omid
Best regards, Omid
Quote:
#ifndef __NetWork_H__
#define __NetWork_H__


Using double underscores in the beginning like this is not only bad practice, it's against the C++ standard.
Quote:
#pragma comment( lib, "Ws2_32.lib" )


Linking instructions inside the source aren't really good style, this is better handled by the build system.
Quote:Original post by Anonymous Poster
Quote:
#ifndef __NetWork_H__
#define __NetWork_H__


Using double underscores in the beginning like this is not only bad practice, it's against the C++ standard.

I suggest using triple underscores, or no underscores at all and a unique prefix.
The only 'style' issue I have with your code is that you use (VOID) for functions taking no parameters. Cleaner would be to use (void), since void is a keyword whereas VOID is some #define, or better no void at all and just write empty parens: ()

Other than that, I think your code is better than 80% of the C++ code I have seen, because it's easily readable even without the comments ('self-documenting code' as its called).
Readability is the most important factor of code quality to me.
Ok, some of your variable names could be a bit longer/descriptive (r).
And I'm not a fan at all of the fashion to prefix a class with C (CIocpBuffer), since you really ought to know that it's a class and not an integer or some such.
Also I don't like prefixing variables with their type (bSomethingBool, iAnInt, cpparfsWhatTheFsckIsThis).

But, your code isn't bad at all.
Quote:Original post by Konfusius
I suggest using triple underscores, or no underscores at all and a unique prefix.


Too bad every triple underscore initiated name is automatically a double underscore name as well, and therefore illegal.

Quote:Original post by Konfusius
since you really ought to know that it's a class and not an integer or some such.
Also I don't like prefixing variables with their type (bSomethingBool, iAnInt, cpparfsWhatTheFsckIsThis).


yeah, i used to do that until i realised that i'd never have variables called

float fName , char* szCounter, int iPtr etc....

i don't really need to be reminded that "name" is a string. If it was something else it'd would probably be time to retire...

CClass isn't all that useful either. again, how often do you declare variables like :

int int;
string string;

99% of the time it's pretty obvious if that thing is an instance or a type.

m_VarName and g_VarName are pretty useful imo. Though, i now tend to do mVarName gVarName or just varName for a local (the underscore becomes pretty useless).

As for the code, it's not a bad style. Get rid of ( VOID ) and replace with (). There's no need for that, it just serves to give you RSI. Also, i'm not a fan or aligning functions
ie,
void   myFunc (int&);string myFunc2(bool&);


that at some point will in-evitably get re-formatted to

void                   myFunc              (int&);string                 myFunc2             (bool&);someVeryLongReturnType someLongFunctionName(bool&);


which if you use SVN/CVS/VSS creates a hell of a lot of noise when looking at past revisions. I always prefer :

void myFunc(int&);string myFunc2(bool&);someVeryLongReturnType someLongFunctionName(bool&);


because it will be most readable in subversion logs.
- Don't use the 'typedef struct' idiom in C++. If you really want a typedef for the pointer, you can do this:

struct COMPLETIONKEY {  SOCKET  s;  void *  o;};typedef COMPLETIONKEY* LPCOMPLETIONKEY;


Same number of (identifiers + keywords) - unless you need more typedefs. But this way is C++ - idiomatic, and saves effort in the most common case of not typedeffing anything besides the struct - plus you don't have to worry about 'tag's.

- Declare variables at first use, initializing them with their initial value where possible.

- Don't declare variables at all where you only need a temporary, unless the expression becomes too complicated or there is a "common subexpression" that you want to give a name to.

- As mentioned, don't tag your variable names.

- If I were you, I'd stick with new-style // comments most of the time.

As a sample -

Old:
    bool Startup()    {        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;         }        /* The WinSock DLL is acceptable. Proceed. */        return true;    }


New (please excuse my difference in brace style and indentation - yours are fine):
bool Startup() {  WSADATA wsaData;  // Can't give an initial value there because it gets initialized by  // use as an out-parameter.  // Look for a usable WinSock DLL, and report an error if not found.  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {    return false;  }  // Ensure that the WinSock DLL supports 2.2 (report an error if  // not supported).  // 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) {    WSACleanup();    return false;   }  // The WinSock DLL is acceptable. Proceed.  return true;}


Oh, might I suggest making an object to represent worker threads? Then the COMPLETIONKEY, IOCPOVERLAPPED and that dwTrans thingy become members, and you don't have to pass them around. BTW, what is this UNREFERENCED_PARAMETER thing? It looks like some kind of macro to keep the compiler quiet about unused function parameters. You should be able to get the same effect by just not providing a name for the parameter when defining the function:

void OnIoAccept(LPCOMPLETIONKEY pCK, LPIOCPOVERLAPPED pOL, DWORD&) {  // Implementation here.  // Writing that way is legal, but it leaves you without a way to refer to  // the DWORD within the function - thus the compiler doesn't complain when  // you don't refer to it. :)}
Thanks all of friends!

i'm happy.

This topic is closed to new replies.

Advertisement