• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Error

            C++博客 首頁 新隨筆 聯系 聚合 管理
              217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks

            簡化后的CNetClient類圖:

            image

             

            本次是分享下整體設計思想,不研究細節網絡實現。

                CNetClient用戶客戶端的網絡處理。主要功能需求如下:

            *能接收遠端數據

            *能把接收到的數據送到上層處理

            *能向遠端發送數據

            **發送和接收都是異步

            **CNetClient本身是一個底層服務,對上層是異步的

             

            針對上述需求GodofMoney實現的非常簡單:

            針對發送和接收單獨開線程,回調OnRecvProc OnSend

            和上層數據交互通過兩個隊列完成,一個發送隊列,一個接收隊列。

            上層將需要發送的數據放到發送隊列,底層將接收到的數據調用上層給的處理函數處理后push出去

             

            先這么多吧,以后還會繼續分析,,,

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

            //////NetClient.h///////////////////////

            //! NetClient.h: interface for the CNetClient class.
            //!發送接收原始網絡包執行類

            #if !defined(AFX_NETCLIENT_H__CF62B9AC_911A_4CE6_81B2_55CB2588A42E__INCLUDED_)
            #define AFX_NETCLIENT_H__CF62B9AC_911A_4CE6_81B2_55CB2588A42E__INCLUDED_

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

            #define SERVERPORT 10012
            #define BUFFER_SIZE 4096

            #include <winsock2.h>
            #pragma comment(lib,"ws2_32.lib")
            #pragma once
            /*******************************************************************************************
            *******************************************************************************************/
            //!錯誤定義:套接字上的數據操作正忙
            #define  CLIENT_FUNERROR 0x100
            //!TCP winsock連接類
            class CClientSocket 
            {
                friend class CNetClient;
            public:
                CClientSocket();
                CClientSocket(bool & bSuccess,int iSockType,char * szSvrAddr,unsigned short iSvrPort)
                {
                    bSuccess=false;
                    bSuccess=CreateSocket(iSockType);
                    bSuccess=ConnectSocket(szSvrAddr,iSvrPort);
                }
                virtual ~CClientSocket();
            public:
                //!釋放資源
                void UnInit();
                //!winsocket處理
                bool CreateSocket(int iSockType){
                    return CreateSocket(&m_Socket,iSockType);
                }
                bool BindSocket(char *szHostAddr,unsigned short  iHostPort){
                    return BindSocket(m_Socket,szHostAddr,iHostPort);
                }
                bool ShutDownSocket(){
                    return ShutDownSocket(m_Socket);
                }
                bool CloseSocekt(){
                    return CloseSocket(m_Socket);
                }
                bool ConnectSocket(char * szDestAddr,unsigned short iDestPort);
                //!發送與接收數據
                /*
                 *char * data        數據指針
                 *DWORD len            數據長度
                 *DWORD *retlen        處理長度
                 *DWORD time        等待時間
                 *返回:true為成功,否則為失敗
                 */
                bool SendMsg(char * data,DWORD len,DWORD *retlen,DWORD time);
                bool RecvMsg(char * data,DWORD len,DWORD *retlen,DWORD time);

                char        m_szDestAddr[255];   
                BOOL        m_bEnData;
            protected:
                bool CreateSocket(SOCKET *pNewSocket,int iSockType);
                bool BindSocket(SOCKET BindSocket,char *szHostAddr,unsigned short iHostPort);
                bool ShutDownSocket(SOCKET nowSocket);
                bool CloseSocket(SOCKET nowSocket);
                bool SendDataS(SOCKET socket,char *data,DWORD len,DWORD *retlen,WSAEVENT hSendEvent,DWORD time);
                bool RecvDataS(SOCKET socket,char *data,DWORD len,DWORD *retlen,WSAEVENT hRecvEvent,DWORD time);
            private:
                bool SendData(SOCKET socket,char *data,DWORD len,DWORD *retlen,WSAEVENT hSendEvent,DWORD time);
                bool RecvData(SOCKET socket,char *data,DWORD len,DWORD *retlen,WSAEVENT hRecvEvent,DWORD time);
            private:
                SOCKET m_Socket;
                WSAEVENT m_hExitEvent;
                struct sockaddr_in inAddr;
            };
            /*******************************************************************************
            消息隊列類:用于存儲消息隊列,即待發送的消息的集合,或者是接收過待處理的集合
            *******************************************************************************/
            template <class T> class Queue;
            //!鏈式隊列結點定義
            template <class T> class QueueNode
            {
                friend class Queue<T>;
            private:
                T data;//!數據域
                QueueNode<T> *link;//!鏈域
                QueueNode(T d,QueueNode *l=NULL):link(l){memcpy(&data,&d,sizeof(T));}//!構造函數
            };
            //!鏈式隊列類定義
            template <class T> class Queue
            {
            public:
                Queue():rear(NULL),front(NULL),count(0){}//!構造函數
                ~Queue();//!析構函數
                void EnQueue(const T & item);//!將item加入到隊列中
                T DeQueue();//!刪除并返回隊頭元素
                T GetFront(){return front->data;}//!查看隊頭元素的值
                void MakeEmpty();//!置空隊列
                int IsEmpty() const {return front==NULL;}//!判斷隊列空否
                int GetSize() const {return count;}
            private:
                QueueNode<T> *front ,*rear;//!隊頭,隊尾指針
                int            count;
            };
            typedef struct _MSG_NODE
            {
                unsigned long DataLength;
                char pData[BUFFER_SIZE];
            }MSG_NODE,*PMSG_NODE;
            /*********************************************************************************/

            //!通過回調函數調用上層處理函數
            typedef void __stdcall ProcessRecvClientData(char * pData,unsigned long DataLength, void *pContext);

            //!內部采用標準三線程模型
            DWORD _stdcall SendProc(LPVOID pParam);
            DWORD _stdcall WorkProc(LPVOID pParam);
            DWORD _stdcall RecvProc(LPVOID pParam);
            //!網絡客戶端類
            class CNetClient 
            {
            public:
                CNetClient();
                virtual ~CNetClient();
            public:
                //!初試化
                /*
                 *ProcessRecvClientData* pProcessRecvClientData        接收數據回調函數
                 *void *pProcessRecvContext                接收數據回調函數上下文
                 *LPCTSTR szSvrAddr                        連接地址
                 *unsigned long iSvrPort=SERVERPORT        連接端口
                 */
                bool Init(ProcessRecvClientData* pProcessRecvClientData,
                    void *pProcessRecvContext,
                    LPCTSTR szSvrAddr,
                    unsigned long iSvrPort=SERVERPORT,
                    BOOL    bEnData = TRUE);
                //!清除跟釋放資源
                void UnInit(BOOL bWait = FALSE);
                //!發送數據
                bool SendMsg(char * pData,unsigned long DataLength);
                //!返回本地地址
                LPCTSTR GetLocalIP(){return IsStart ? HostIpAddr:NULL;}
                bool IsStarted(){return IsStart;}
            protected:
                int InitNetWork(LPCTSTR szSvrAddr,
                    unsigned int SvrPort=SERVERPORT,
                    LPCTSTR HostIpAddr=NULL);
                void WriteLogString(LPCTSTR strLog);

                CClientSocket m_sClient;
                ProcessRecvClientData* m_pProcessRecvClientData;
                void*             m_pProcessRecvContext;
                Queue <MSG_NODE> SendMsgQueue;
                CRITICAL_SECTION SendMsgQueSection;
                HANDLE hSendEvent;
                Queue <MSG_NODE> RecvMsgQueue;
                CRITICAL_SECTION RecvMsgQueSection;
                //!開始工作事件
                HANDLE hWorkEvent;
                //!退出事件   
                HANDLE hExitEvent;
                //!是否用戶進行了反初始化操作,如果是:接收線程將不再調用回調函數
                bool bOprUnInit;
                //!是否已經被驅動
                bool IsStart;
                TCHAR HostIpAddr[16];

                BOOL m_bEnData;

                //!線程資源
                HANDLE RecvHan;
                HANDLE WorkHan;
                HANDLE ThreHan;
                static DWORD WINAPI SendProc(LPVOID pParam);
                static DWORD WINAPI WorkProc(LPVOID pParam);
                static DWORD WINAPI RecvProc(LPVOID pParam);
                void  OnSendProc();
                void  OnWorkProc();
                void  OnRecvProc();
            };
            #endif //! !defined(AFX_NETCLIENT_H__CF62B9AC_911A_4CE6_81B2_55CB2588A42E__INCLUDED_)

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

            /////CNetClient.cpp//////////////////////////

            // NetClient.cpp: implementation of the CNetClient class.
            //
            //////////////////////////////////////////////////////////////////////

            #include "stdafx.h"
            #include <atlbase.h>
            #include "NetClient.h"
            #include "EnDeData.h"
            #include <fstream>
            using namespace std;
            #define  W2A

            //////////////////////////////////////////////////////////////////////
            // Construction/Destruction
            //////////////////////////////////////////////////////////////////////
            CNetClient::CNetClient()
            {
                IsStart=false;
                bOprUnInit=false;
                m_pProcessRecvClientData=NULL;
                m_pProcessRecvContext = NULL;
                WorkHan = NULL;
                RecvHan = NULL;
                ThreHan = NULL;
                hSendEvent=CreateEvent(NULL,false,false,NULL);
                hWorkEvent=CreateEvent(NULL,false,false,NULL);
                hExitEvent=CreateEvent(NULL,false,false,NULL);
            }
            CNetClient::~CNetClient()
            {
                CloseHandle(hSendEvent);
                CloseHandle(hWorkEvent);
                CloseHandle(hExitEvent);
            }
            DWORD  CNetClient::SendProc(LPVOID pParam)
            {
                reinterpret_cast<CNetClient*>(pParam)->OnSendProc();
                return 0;
            }
            void CNetClient::OnSendProc()
            {
                CNetClient * pNetClient=(CNetClient*) this;
                HANDLE event[2];
                event[0]=pNetClient->hSendEvent;
                event[1]=pNetClient->hExitEvent;

                while(true)
                {
                    Sleep(10);
                    ::EnterCriticalSection(&pNetClient->SendMsgQueSection);
                    //隊列為空,等待發送事件觸發
                    if(pNetClient->SendMsgQueue.IsEmpty())
                    {
                        ::LeaveCriticalSection(&pNetClient->SendMsgQueSection);
                        //為空,或者發送完畢
                        ResetEvent(pNetClient->hSendEvent);
                        //TRACE("\nTheSendProc Is Waiting....");   
                        DWORD Index=::WaitForMultipleObjects(2,event,false, 50);
                        if((Index-WAIT_OBJECT_0) == WAIT_TIMEOUT)
                        {
                            if(pNetClient->bOprUnInit)
                            {
                                return ;//應用程序請求退出   
                            }
                        }
                        else if((Index-WAIT_OBJECT_0)==1)
                        {
                            return ;
                        }
                    }
                    else
                    {
                        //取下一個結點,并發送
                        MSG_NODE p=pNetClient->SendMsgQueue.DeQueue();
                        //釋放隊列
                        ::LeaveCriticalSection(&pNetClient->SendMsgQueSection);
                        DWORD retlen;
                        bool bRet=pNetClient->m_sClient.SendMsg(p.pData,p.DataLength,&retlen,WSA_INFINITE);
                        if(bRet==false || retlen!=p.DataLength)
                        {
                            if(GetLastError()!=CLIENT_FUNERROR)
                            pNetClient->m_pProcessRecvClientData(NULL,0, pNetClient->m_pProcessRecvContext);
                            //pNetClient->UnInit();
                        }   
                    }
                }
                return ;
            }
            DWORD  CNetClient::WorkProc(LPVOID pParam)
            {
                reinterpret_cast<CNetClient*>(pParam)->OnWorkProc();
                return 0;
            }

            void CNetClient::OnWorkProc()
            {
                CNetClient* pNetClient=(CNetClient*)this;
                HANDLE event[2];
                event[0]=pNetClient->hWorkEvent;
                event[1]=pNetClient->hExitEvent;
                while(true)
                {
                    //Sleep(1);
                    ::EnterCriticalSection(&pNetClient->RecvMsgQueSection);
                    //隊列為空,等待發送事件觸發
                    if(pNetClient->RecvMsgQueue.IsEmpty())
                    {
                        ::LeaveCriticalSection(&pNetClient->RecvMsgQueSection);
                        //為空,或者發送完畢
                        ResetEvent(pNetClient->hWorkEvent);
                        //TRACE("\nTheWorkProc Is Waiting....");           
                        DWORD Index=::WaitForMultipleObjects(2,event,false, 100);
                        if((Index-WAIT_OBJECT_0) == WAIT_TIMEOUT)
                        {
                            if(pNetClient->bOprUnInit)
                            {
                                return ;//應用程序請求退出   
                            }
                        }
                        else if((Index-WAIT_OBJECT_0)==1)
                        {
                            return ;
                        }
                    }
                    else
                    {
                        //取下一個結點,并發送
                        MSG_NODE p=pNetClient->RecvMsgQueue.DeQueue();
                        //釋放隊列
                        ::LeaveCriticalSection(&pNetClient->RecvMsgQueSection);
                        //調用回調函數,處理數據
                        if(m_bEnData)
                        {
                            char outData[4096];
                            long outLen = 4096;
                            DeData(p.pData, p.DataLength, outData, outLen);
                            pNetClient->m_pProcessRecvClientData(outData,outLen, pNetClient->m_pProcessRecvContext);
                        }
                        else
                        {
                            pNetClient->m_pProcessRecvClientData(p.pData,p.DataLength, pNetClient->m_pProcessRecvContext);

                        }
                    }
                }
                return ;
            }
            DWORD CNetClient::RecvProc(LPVOID pParam)
            {
                try
                {
                    reinterpret_cast<CNetClient*>(pParam)->OnRecvProc();
                }
                catch (...) {
                }
                return 0;
            }
            void CNetClient::OnRecvProc()
            {
                char RecvBuf[BUFFER_SIZE];
                DWORD retlen;
                while (true)
                {
                    //Sleep(1);
                    //TRACE("\nTheRecvThread Is Waiting...");
                    if(!m_sClient.RecvMsg(RecvBuf,BUFFER_SIZE,&retlen,WSA_INFINITE) &&  GetLastError()!=CLIENT_FUNERROR)
                    {
                        if(bOprUnInit)
                        {
                            return ;//應用程序請求退出   
                        }
                        //連接已經被斷開,通知上層(通過調用回調函數)
                        m_pProcessRecvClientData(NULL,0, m_pProcessRecvContext);
                        //pNetClient->UnInit();
                        return ;
                    }
                    else
                    {
                        if(bOprUnInit)
                        {
                            return ;//應用程序請求退出   
                        }
                        //沒收到字節?還是出錯
                        if(retlen==0 || retlen > BUFFER_SIZE)
                        {
                            m_pProcessRecvClientData(NULL,0, m_pProcessRecvContext);
                            //pNetClient->UnInit();
                            return ;
                        }
                        //將接收到的數據放到接收隊列里
                        MSG_NODE Msg;
                        Msg.DataLength=retlen;
                        memcpy(Msg.pData,RecvBuf,retlen);

                        //插入消息隊列
                        ::EnterCriticalSection(&RecvMsgQueSection);
                        if(RecvMsgQueue.IsEmpty())
                        {
                            RecvMsgQueue.EnQueue(Msg);
                            ::LeaveCriticalSection(&RecvMsgQueSection);
                            //如果消息隊列為空,告訴工作線程可以進行工作了
                            SetEvent(hWorkEvent);
                        }
                        else
                        {
                            if(RecvMsgQueue.GetSize() > 50)
                            {
                                if(!m_bEnData)
                                    RecvMsgQueue.MakeEmpty();
                            }
                            RecvMsgQueue.EnQueue(Msg);

                            ::LeaveCriticalSection(&RecvMsgQueSection);
                        }
                    }
                }
                return ;
            }
            bool CNetClient::Init(ProcessRecvClientData* pProcessRecvClientData,
                                  void *pProcessRecvContext,
                                  LPCTSTR szSvrAddr,
                                  unsigned long iSvrPort,
                                  BOOL    bEnData)
            {
                if(pProcessRecvClientData==NULL //回調函數空
                    || szSvrAddr==NULL //地址空
                    || IsStart)//已經啟動過了
                {
                    return false;   
                }

                m_bEnData = bEnData;
                m_sClient.m_bEnData = bEnData;

                ::InitializeCriticalSection(&SendMsgQueSection);
                ::InitializeCriticalSection(&RecvMsgQueSection);   
                ResetEvent(hExitEvent);
                IsStart    = false;
                bOprUnInit = false;
                m_pProcessRecvClientData = pProcessRecvClientData;
                m_pProcessRecvContext    = pProcessRecvContext;
                int  bRet=InitNetWork(szSvrAddr,iSvrPort,HostIpAddr);
                if(0==bRet)
                {
                    IsStart = true;
                    return true;
                }
                else
                {
                    m_sClient.UnInit();   
                    ::DeleteCriticalSection(&SendMsgQueSection);
                    ::DeleteCriticalSection(&RecvMsgQueSection);   
                    return false;
                }

            }
            void CNetClient::UnInit(BOOL bWait)
            {
                if(!IsStart)
                    return;

                IsStart=false;
                bOprUnInit=true;
                if(hExitEvent)
                    SetEvent(hExitEvent);
                if(m_sClient.m_hExitEvent)
                    WSASetEvent(m_sClient.m_hExitEvent);

                if(RecvHan)
                {
                    /*
                    if(bWait)
                    {
                        bool bloop = true;
                        while(bloop)
                        {
                            if(WaitForSingleObject(RecvHan, 1500) == WAIT_TIMEOUT)
                            {
                                if(RecvHan == NULL)
                                    bloop =false;
                            }
                            else
                            {
                                bloop =false;
                            }
                        }
                    }
                    else
                    {
                        if(WaitForSingleObject(RecvHan, bWait ? INFINITE : 1500) == WAIT_TIMEOUT)
                        {
                            TerminateThread(RecvHan, -2);
                        }
                    }*/
                    if(WaitForSingleObject(RecvHan,3000) == WAIT_TIMEOUT)
                    {
                        TerminateThread(RecvHan, -2);
                    }
                    CloseHandle(RecvHan);
                    RecvHan = NULL;
                }
                if(WorkHan)
                {
                    /*
                    if(bWait)
                    {
                        bool bloop = true;
                        while(bloop)
                        {
                            if(WaitForSingleObject(WorkHan, 1500) == WAIT_TIMEOUT)
                            {
                                if(WorkHan == NULL)
                                    bloop =false;
                            }
                            else
                            {
                                bloop =false;
                            }
                        }
                    }
                    else
                    {
                        if(WaitForSingleObject(WorkHan, bWait ? INFINITE : 1500) == WAIT_TIMEOUT)
                            TerminateThread(WorkHan, -2);
                    }*/
                    if(WaitForSingleObject(WorkHan,3000) == WAIT_TIMEOUT)
                    {
                        TerminateThread(WorkHan, -2);
                    }
                    CloseHandle(WorkHan);
                    WorkHan = NULL;
                }
                if(ThreHan)
                {
                    /*
                    if(bWait)
                    {
                        bool bloop = true;
                        while(bloop)
                        {
                            if(WaitForSingleObject(ThreHan, 1500) == WAIT_TIMEOUT)
                            {
                                if(ThreHan == NULL)
                                    bloop =false;
                            }
                            else
                            {
                                bloop =false;
                            }
                        }
                    }
                    else
                    {
                        if(WaitForSingleObject(ThreHan, bWait ? INFINITE : 1500) == WAIT_TIMEOUT)
                            TerminateThread(ThreHan, -2);
                    }*/
                    if(WaitForSingleObject(ThreHan,3000) == WAIT_TIMEOUT)
                    {
                        TerminateThread(ThreHan, -2);
                    }
                    CloseHandle(ThreHan);
                    ThreHan = NULL;
                }
                m_sClient.UnInit();   
                ::DeleteCriticalSection(&SendMsgQueSection);
                ::DeleteCriticalSection(&RecvMsgQueSection);
                SendMsgQueue.MakeEmpty();
                RecvMsgQueue.MakeEmpty();   
                m_pProcessRecvClientData=NULL;
                m_pProcessRecvContext = NULL;
            }
            int CNetClient::InitNetWork(LPCTSTR szSvrAddr,
                                        unsigned int SvrPort,
                                        LPCTSTR pHostIpAddress)
            {
                int Error=0;
                WSADATA wsaData;
                memset((void *)pHostIpAddress,0,sizeof(pHostIpAddress));
                //Net Start Up
                /*
                char Name[100];
                hostent *pHostEntry;
                in_addr rAddr;
                Error=WSAStartup(MAKEWORD(0x02,0x02),&wsaData);
                if(Error!=0)
                {
                    Error = WSAGetLastError();
                    //LogStr.Format("WSAStartUp Faild With Error: %d",Error);
                    //WriteLogString(LogStr);

                    return Error;
                }
                //Make Version
                if ( LOBYTE( wsaData.wVersion ) != 2 ||
                     HIBYTE( wsaData.wVersion ) != 2 )
                {
                    WSACleanup( );
                    //WriteLogString("The Local Net Version Is not 2");

                    return -1;
                }*/
                //Get Host Ip
                /*Error = gethostname ( Name, sizeof(Name) );
                if( 0 == Error )
                {
                    pHostEntry = gethostbyname( Name );
                    if( pHostEntry != NULL )
                    {
                        memcpy( &rAddr, pHostEntry->h_addr_list[0], sizeof(struct in_addr) );
                        sprintf((char * )pHostIpAddress,"%s",inet_ntoa( rAddr ));
                    }
                    else
                    {
                        Error = WSAGetLastError();
                        //LogStr.Format("GetHostIp faild with Error: %d",Error);
                        //WriteLogString(LogStr);

                    }
                }
                else
                {
                    Error = WSAGetLastError();
                    //LogStr.Format("gethostname faild with Error: %d",Error);
                    //WriteLogString(LogStr);
                }*/
                //Socket Create
                if(0==Error)
                {
                    if(!m_sClient.CreateSocket(SOCK_STREAM))
                    {
                        Error=WSAGetLastError();
                        //LogStr.Format("Create Client Socket Faild :%d",Error);
                        ////WriteLogString(LogStr);
                        return Error;
                    }
                }
                if(0==Error)
                {
                    //fix me
                    USES_CONVERSION;
                    if(!m_sClient.ConnectSocket((char *)W2A(szSvrAddr),SvrPort))
                    {
                        Error=WSAGetLastError();
                        //LogStr.Format("Create Client Socket Faild :%d",Error);
                        //WriteLogString(LogStr);
                        return -1;
                    }
                }
                //啟動工作線程,并升高工作線程的等級至最高
                if(0==Error)
                {
                    unsigned long WorkID;
                    if((WorkHan=CreateThread(NULL,
                        0,
                        WorkProc,
                        this,
                        0,
                        &WorkID))==NULL)
                    {
                        Error=GetLastError();
                        //LogStr.Format("Create WorkThread Faild With Error %d",Error);
                        //WriteLogString(LogStr);
                        return Error;
                    }
                    SetThreadPriority(WorkHan,THREAD_PRIORITY_HIGHEST);
                }
                //啟動接收線程
                if(0==Error)
                {
                    unsigned long RecvID;
                    if((RecvHan=CreateThread(NULL,
                        0,
                        RecvProc,
                        this
                        ,
                        0,
                        &RecvID))==NULL)
                    {
                        Error=GetLastError();
                        //LogStr.Format("Create RecvThread Faild With Error %d",Error);
                        //WriteLogString(LogStr);
                        SetEvent(hExitEvent);//退出先前創建的線程
                        return Error;
                    }
                }
                //啟動發送線程
                if(0==Error)
                {
                    unsigned long ThrID;
                    if((ThreHan=CreateThread(NULL,
                        0,
                        SendProc,
                        this,
                        0,
                        &ThrID))==NULL)
                    {
                        Error=GetLastError();
                        //LogStr.Format("Create SEND Thred Faild With Error %d",Error);
                        //WriteLogString(LogStr);
                        SetEvent(hExitEvent);//退出先前創建的線程
                        return Error;
                    }
                }
                return Error;
            }
            bool CNetClient::SendMsg(char * pData,unsigned long DataLength)
            {       
                    //未調用初始化函數
                    if(!IsStart || pData==NULL || DataLength==0)return false;
                    //構造消息
                    MSG_NODE Msg;
                    Msg.DataLength=DataLength;
                    memcpy(Msg.pData,pData,DataLength);
                    //插入消息隊列
                    ::EnterCriticalSection(&SendMsgQueSection);
                    if(SendMsgQueue.IsEmpty())
                    {
                        SendMsgQueue.EnQueue(Msg);
                        ::LeaveCriticalSection(&SendMsgQueSection);
                        //如果消息隊列為空,告訴等待的發送線程可以發送了
                        SetEvent(hSendEvent);
                    }
                    else
                    {
                        SendMsgQueue.EnQueue(Msg);
                        ::LeaveCriticalSection(&SendMsgQueSection);
                    }
                    return true;
            }
            void CNetClient::WriteLogString(LPCTSTR strLog)
            {
                return;
            }
            /********************************************************************
            函數名  : Queue<T>::~Queue()
            輸入參數:
            輸出參數:
            功能描述: 隊列析構函靈敏,清空所有隊列元素
            全局變量: 無
            調用模塊:
            附加說明:
            ********************************************************************/
            template <class T>  Queue<T>::~Queue()
            {
                QueueNode<T> *p=front;
                while(front!=NULL)
                {
                    p=front;
                    front=front->link;
                    delete p;
                }
            }
            /********************************************************************
            函數名  : Queue<T>::EnQueue
            輸入參數:
            const T & item :要插入的結點的引用
            輸出參數:
            功能描述: 在隊列中插入一個結點
            全局變量: 無
            調用模塊:
            附加說明:
            ********************************************************************/
            template <class T> void Queue<T>::EnQueue(const T & item)
            {
                count ++;
                if(front==NULL)front=rear=new QueueNode<T>(item,NULL);
                else rear=rear->link=new QueueNode<T>(item,NULL);
            }
            /********************************************************************
            函數名  : Queue<T>::DeQueue()
            輸入參數:
            T  :返回被刪除結點的值
            輸出參數:
            功能描述: 從隊列中取出一個結點,并返回該結點的值
            全局變量: 無
            調用模塊:
            附加說明:
            ********************************************************************/
            template <class T> T Queue<T>::DeQueue()
            {
                T  retvalue;
                memset(&retvalue,0,sizeof(T));
                if(IsEmpty())
                    return retvalue;
                count --;
                QueueNode<T> * p=front;
                retvalue=p->data;
                front=front->link;
                delete p;
                return retvalue;
            }
            /********************************************************************
            函數名  : Queue<T>::MakeEmpty()
            輸入參數:
            輸出參數:
            功能描述: 將隊列元素清空
            全局變量: 無
            調用模塊:
            附加說明:
            ********************************************************************/
            template <class T> void Queue<T>::MakeEmpty()
            {
                if(front==NULL)return ;
                QueueNode<T> * p=front;
                while(front!=NULL)
                {
                    p=front;
                    front=front->link;
                    delete p;
                }
                front=rear=NULL;
                count = 0;
            }
            /*************************************************************************/
            CClientSocket::CClientSocket()
            {
                inAddr.sin_addr.s_addr = INADDR_NONE;
                m_hExitEvent = NULL;
                m_Socket = 0;
                m_szDestAddr[0] = '\0';   
            }           
            CClientSocket::~CClientSocket()
            {
                if(m_hExitEvent != NULL)
                    WSACloseEvent(m_hExitEvent);
            }
            void CClientSocket::UnInit()
            {
                if(m_hExitEvent != NULL)
                    WSACloseEvent(m_hExitEvent);
                ShutDownSocket();
                CloseSocekt();
                m_szDestAddr[0] = '\0';   
                m_Socket = 0;
                m_hExitEvent = 0;
                //    if(m_hExitEvent != (WSAEVENT)0xcccccccc)WSACloseEvent(m_hExitEvent);
            }
            bool CClientSocket::CreateSocket(SOCKET *pNewSocket,int iSockType)
            {
                if(m_hExitEvent != NULL)
                    WSACloseEvent(m_hExitEvent);
                m_hExitEvent=WSACreateEvent();
                WSAResetEvent(m_hExitEvent);
                bool bok =  ((*pNewSocket=WSASocket(AF_INET,iSockType,0,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)?
                    false:true;
                if(bok)
                {
                    int nrcvbuf=1024*68;
                    int     err=setsockopt(*pNewSocket, SOL_SOCKET, SO_RCVBUF,(char*)&nrcvbuf, sizeof(nrcvbuf));
                    err=setsockopt(*pNewSocket, SOL_SOCKET, SO_SNDBUF,(char*)&nrcvbuf, sizeof(nrcvbuf));

                    int TimeOut=10000; //設置發送超時6秒
                    if(::setsockopt(*pNewSocket,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
                        return 0;
                    }
                    TimeOut=10000;//設置接收超時6秒
                    if(::setsockopt(*pNewSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
                        return 0;
                    }

                }
                return bok;
            }
            bool CClientSocket::BindSocket(SOCKET BindSocket,char *szHostAddr,unsigned short iHostPort)
            {
                struct sockaddr_in inAddr;
                inAddr.sin_addr.S_un.S_addr=inet_addr(szHostAddr);
                inAddr.sin_family=AF_INET;
                inAddr.sin_port=htons(iHostPort);
                return (bind(BindSocket,(PSOCKADDR)&inAddr,sizeof(inAddr)))
                    ==SOCKET_ERROR?false:true;
            }
            bool CClientSocket::ShutDownSocket(SOCKET nowSocket)
            {
                if(nowSocket)
                    return shutdown(nowSocket,SD_BOTH)?false:true;
                return true;
            }
            bool CClientSocket::CloseSocket(SOCKET nowSocket)
            {
                bool bok = false;
                if(nowSocket)
                    bok =  (closesocket(nowSocket)==SOCKET_ERROR)?false:true;
                m_Socket = 0;
                return bok;
            }
            bool CClientSocket::SendData(SOCKET socket,char *data,DWORD len,DWORD *retlen,WSAEVENT hSendEvent,DWORD time)
            {
                if((int)len <= 0 || len > 4096)
                    return true;
                WSABUF DataBuf;
                WSAEVENT hEvents[2];
                WSAOVERLAPPED SendOverLapp;
                DWORD flag;
                char outData[4096];
                long outLen = 4096;
                if(m_bEnData)
                {
                    EnData(data, len, outData, outLen);
                    DataBuf.buf=outData;
                    DataBuf.len=outLen;

                }
                else
                {
                    DataBuf.buf=data;
                    DataBuf.len=len;
                }
                hEvents[0]=m_hExitEvent;
                hEvents[1]=hSendEvent;
                memset(&SendOverLapp,0,sizeof(WSAOVERLAPPED));
                SendOverLapp.hEvent=hSendEvent;
                flag=0;
                /////////////////////////////////////
                //Godzilar
                int ret;
                if((ret=WSASend(socket,&DataBuf,1,retlen,flag,&SendOverLapp,NULL))==0)
                {
                    *retlen = len;
                    return true;
                }
                else if((ret==SOCKET_ERROR)&&(WSAGetLastError()==WSA_IO_PENDING))
                {
                    DWORD EventCaused=WSAWaitForMultipleEvents(2,hEvents,FALSE,time,FALSE);
                    WSAResetEvent(hSendEvent);
                    if(EventCaused == WSA_WAIT_FAILED || EventCaused == WAIT_OBJECT_0)
                    {
                        if(EventCaused == WAIT_OBJECT_0)
                            SetLastError(CLIENT_FUNERROR);
                        return false;
                    }
                    flag=0;
                    return WSAGetOverlappedResult(socket,&SendOverLapp,retlen,false,&flag)?
                        true:false;
                }
                else
                    return false;
            }
            bool CClientSocket::RecvData(SOCKET socket,char *data,DWORD len,DWORD *retlen,WSAEVENT hRecvEvent,DWORD time)
            {
                WSABUF DataBuf;
                WSAEVENT hEvents[2];
                WSAOVERLAPPED RecvOverLapp;
                DWORD flag;

                hEvents[0]=m_hExitEvent;
                hEvents[1]=hRecvEvent;
                DataBuf.buf=data;
                DataBuf.len=len;
                memset(&RecvOverLapp,0,sizeof(WSAOVERLAPPED));
                RecvOverLapp.hEvent=hRecvEvent;
                flag=0;
                /////////////////////////////////////
                int ret;
                if((ret=WSARecv(socket,&DataBuf,1,retlen,&flag,&RecvOverLapp,NULL))==0)
                {
                    return true;
                }
                else if((ret==SOCKET_ERROR)&&(WSAGetLastError()==WSA_IO_PENDING))
                {
                    DWORD EventCaused=WSAWaitForMultipleEvents(2,hEvents,false,time,false);
                    WSAResetEvent(hRecvEvent);
                    if(EventCaused == WSA_WAIT_FAILED || EventCaused == WAIT_OBJECT_0)
                    {
                        if(EventCaused == WAIT_OBJECT_0)
                            SetLastError(CLIENT_FUNERROR);
                        return false;
                    }
                    flag=0;
                    return WSAGetOverlappedResult(socket,&RecvOverLapp,retlen,false,&flag)?
                        true:false;
                }
                else
                    return false;
            }
            bool CClientSocket::SendDataS(SOCKET socket,char *data,DWORD len,DWORD *retlen,WSAEVENT hSendEvent,DWORD time)
            {
                DWORD left,idx,thisret;
                left=len;
                idx=0;
                int oflag=0;
                while(left>0)
                {
                    if(!SendData(socket,&data[idx],left,&thisret,hSendEvent,time))
                    {
                        *retlen=0;
                        return false;
                    }
                    WSAResetEvent(hSendEvent);
                    left-=thisret;
                    idx+=thisret;
                    if(thisret==0)
                    {
                        oflag++;
                        if(oflag>5)
                            break;
                    }
                }
                *retlen=idx;
                return (idx==len)?true:false;
            }
            bool CClientSocket::RecvDataS(SOCKET socket,char *data,DWORD len,DWORD *retlen,WSAEVENT hRecvEvent,DWORD time)
            {
                DWORD left,idx,thisret;
                left=len;
                idx=0;
                int oflag=0;
                while(left>0)
                {
                    if(!RecvData(socket,&data[idx],left,&thisret,hRecvEvent,time))
                    {
                        *retlen=0;
                        return false;
                    }
                    WSAResetEvent(hRecvEvent);
                    left-=thisret;
                    idx+=thisret;
                    if(thisret==0)
                    {
                        oflag++;
                        if(oflag>5)
                            break;
                    }
                }
                *retlen=idx;
                return (idx==len)?true:false;
            }
            bool CClientSocket::SendMsg(char * data,DWORD len,DWORD *retlen,DWORD time)
            {
                WSAEVENT hEvent=WSACreateEvent();
                bool bSend=SendDataS(m_Socket,data,len,retlen,hEvent,time);
                WSACloseEvent(hEvent);
                return bSend;
            }
            bool CClientSocket::RecvMsg(char * data,DWORD len,DWORD *retlen,DWORD time)
            {   
                WSAEVENT hEvent=WSACreateEvent();
                bool Recv=RecvData(m_Socket,data,len,retlen,hEvent,time);
                WSACloseEvent(hEvent);
                return Recv;
            }
            bool CClientSocket::ConnectSocket(char * szDestAddr,unsigned short iDestPort)
            {
                inAddr.sin_family=AF_INET;
                inAddr.sin_port=htons(iDestPort);
                inAddr.sin_addr.S_un.S_addr=inet_addr(szDestAddr);
                if (inAddr.sin_addr.s_addr == INADDR_NONE)
                {
                    LPHOSTENT lphost;
                    lphost = gethostbyname(szDestAddr);
                    if (lphost != NULL)
                        inAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
                    else
                    {
                        WSASetLastError(WSAEINVAL);
                        return FALSE;
                    }
                }
                strcpy(m_szDestAddr, szDestAddr);
                //設置非阻塞方式連接
                unsigned long ul = 1;
                int ret = ioctlsocket(m_Socket, FIONBIO, (unsigned long*)&ul);
                if(ret==SOCKET_ERROR) return 0;

                bool bOK = (connect(m_Socket,(PSOCKADDR)&inAddr,sizeof(inAddr)))
                    ==SOCKET_ERROR ? false:true;
                if(bOK)
                {
                    unsigned long ul1= 0 ;
                    ret = ioctlsocket(m_Socket, FIONBIO, (unsigned long*)&ul1);
                    return bOK;
                }

                //select 模型,即設置超時
                struct timeval timeout ;
                fd_set r;

                FD_ZERO(&r);
                FD_SET(m_Socket, &r);
                timeout.tv_sec = 4; //連接超時15秒
                timeout.tv_usec =50000;
                ret = select(0, 0, &r, 0, &timeout);
                if ( ret <= 0 )
                {
                    bOK = false;
                }
                else
                    bOK = true;

                //一般非鎖定模式套接比較難控制,可以根據實際情況考慮 再設回阻塞模式
                unsigned long ul1= 0 ;
                ret = ioctlsocket(m_Socket, FIONBIO, (unsigned long*)&ul1);
                if(ret==SOCKET_ERROR){
                    bOK = false;
                }

                return bOK;
            }

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

            posted on 2012-10-11 17:34 Enic 閱讀(412) 評論(0)  編輯 收藏 引用 所屬分類: 代碼片段分享
            A级毛片无码久久精品免费| 久久综合九色综合久99 | 久久久久亚洲精品中文字幕| 久久人人爽人人爽人人片av高请| 日日狠狠久久偷偷色综合免费| 色综合久久天天综合| 精品国产福利久久久| 久久Av无码精品人妻系列| 久久综合给合久久狠狠狠97色69| 久久精品国产男包| 久久久久久久精品妇女99| 日韩精品久久久久久久电影| 四虎国产精品免费久久| 香蕉久久永久视频| 欧美亚洲国产精品久久| 五月丁香综合激情六月久久| 久久久噜噜噜久久熟女AA片| AV狠狠色丁香婷婷综合久久| 久久国产乱子精品免费女| 国产A级毛片久久久精品毛片| 国产巨作麻豆欧美亚洲综合久久 | 亚洲国产精品久久久久婷婷软件| 久久国产乱子精品免费女| 国产激情久久久久影院老熟女免费| 亚洲国产精品久久久久婷婷软件| 久久精品无码一区二区日韩AV| 要久久爱在线免费观看| 久久精品一本到99热免费| 人妻精品久久无码专区精东影业| av国内精品久久久久影院| 成人a毛片久久免费播放| 亚洲国产婷婷香蕉久久久久久| 久久久国产精华液| 2022年国产精品久久久久| 久久不见久久见免费影院www日本| 亚洲国产精品嫩草影院久久| 精品久久久久久国产潘金莲 | 亚洲国产成人精品91久久久| 亚洲乱码中文字幕久久孕妇黑人 | 亚洲国产小视频精品久久久三级| 少妇人妻88久久中文字幕|