青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Error

C++博客 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
  217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks

簡(jiǎn)化后的CNetClient類圖:

image

 

本次是分享下整體設(shè)計(jì)思想,不研究細(xì)節(jié)網(wǎng)絡(luò)實(shí)現(xiàn)。

    CNetClient用戶客戶端的網(wǎng)絡(luò)處理。主要功能需求如下:

*能接收遠(yuǎn)端數(shù)據(jù)

*能把接收到的數(shù)據(jù)送到上層處理

*能向遠(yuǎn)端發(fā)送數(shù)據(jù)

**發(fā)送和接收都是異步

**CNetClient本身是一個(gè)底層服務(wù),對(duì)上層是異步的

 

針對(duì)上述需求GodofMoney實(shí)現(xiàn)的非常簡(jiǎn)單:

針對(duì)發(fā)送和接收單獨(dú)開(kāi)線程,回調(diào)OnRecvProc OnSend

和上層數(shù)據(jù)交互通過(guò)兩個(gè)隊(duì)列完成,一個(gè)發(fā)送隊(duì)列,一個(gè)接收隊(duì)列。

上層將需要發(fā)送的數(shù)據(jù)放到發(fā)送隊(duì)列,底層將接收到的數(shù)據(jù)調(diào)用上層給的處理函數(shù)處理后push出去

 

先這么多吧,以后還會(huì)繼續(xù)分析,,,

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

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

//! NetClient.h: interface for the CNetClient class.
//!發(fā)送接收原始網(wǎng)絡(luò)包執(zhí)行類

#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
/*******************************************************************************************
*******************************************************************************************/
//!錯(cuò)誤定義:套接字上的數(shù)據(jù)操作正忙
#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);
    //!發(fā)送與接收數(shù)據(jù)
    /*
     *char * data        數(shù)據(jù)指針
     *DWORD len            數(shù)據(jù)長(zhǎng)度
     *DWORD *retlen        處理長(zhǎng)度
     *DWORD time        等待時(shí)間
     *返回: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;
};
/*******************************************************************************
消息隊(duì)列類:用于存儲(chǔ)消息隊(duì)列,即待發(fā)送的消息的集合,或者是接收過(guò)待處理的集合
*******************************************************************************/
template <class T> class Queue;
//!鏈?zhǔn)疥?duì)列結(jié)點(diǎn)定義
template <class T> class QueueNode
{
    friend class Queue<T>;
private:
    T data;//!數(shù)據(jù)域
    QueueNode<T> *link;//!鏈域
    QueueNode(T d,QueueNode *l=NULL):link(l){memcpy(&data,&d,sizeof(T));}//!構(gòu)造函數(shù)
};
//!鏈?zhǔn)疥?duì)列類定義
template <class T> class Queue
{
public:
    Queue():rear(NULL),front(NULL),count(0){}//!構(gòu)造函數(shù)
    ~Queue();//!析構(gòu)函數(shù)
    void EnQueue(const T & item);//!將item加入到隊(duì)列中
    T DeQueue();//!刪除并返回隊(duì)頭元素
    T GetFront(){return front->data;}//!查看隊(duì)頭元素的值
    void MakeEmpty();//!置空隊(duì)列
    int IsEmpty() const {return front==NULL;}//!判斷隊(duì)列空否
    int GetSize() const {return count;}
private:
    QueueNode<T> *front ,*rear;//!隊(duì)頭,隊(duì)尾指針
    int            count;
};
typedef struct _MSG_NODE
{
    unsigned long DataLength;
    char pData[BUFFER_SIZE];
}MSG_NODE,*PMSG_NODE;
/*********************************************************************************/

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

//!內(nèi)部采用標(biāo)準(zhǔn)三線程模型
DWORD _stdcall SendProc(LPVOID pParam);
DWORD _stdcall WorkProc(LPVOID pParam);
DWORD _stdcall RecvProc(LPVOID pParam);
//!網(wǎng)絡(luò)客戶端類
class CNetClient 
{
public:
    CNetClient();
    virtual ~CNetClient();
public:
    //!初試化
    /*
     *ProcessRecvClientData* pProcessRecvClientData        接收數(shù)據(jù)回調(diào)函數(shù)
     *void *pProcessRecvContext                接收數(shù)據(jù)回調(diào)函數(shù)上下文
     *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);
    //!發(fā)送數(shù)據(jù)
    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;
    //!開(kāi)始工作事件
    HANDLE hWorkEvent;
    //!退出事件   
    HANDLE hExitEvent;
    //!是否用戶進(jìn)行了反初始化操作,如果是:接收線程將不再調(diào)用回調(diào)函數(shù)
    bool bOprUnInit;
    //!是否已經(jīng)被驅(qū)動(dòng)
    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);
        //隊(duì)列為空,等待發(fā)送事件觸發(fā)
        if(pNetClient->SendMsgQueue.IsEmpty())
        {
            ::LeaveCriticalSection(&pNetClient->SendMsgQueSection);
            //為空,或者發(fā)送完畢
            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 ;//應(yīng)用程序請(qǐng)求退出   
                }
            }
            else if((Index-WAIT_OBJECT_0)==1)
            {
                return ;
            }
        }
        else
        {
            //取下一個(gè)結(jié)點(diǎn),并發(fā)送
            MSG_NODE p=pNetClient->SendMsgQueue.DeQueue();
            //釋放隊(duì)列
            ::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);
        //隊(duì)列為空,等待發(fā)送事件觸發(fā)
        if(pNetClient->RecvMsgQueue.IsEmpty())
        {
            ::LeaveCriticalSection(&pNetClient->RecvMsgQueSection);
            //為空,或者發(fā)送完畢
            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 ;//應(yīng)用程序請(qǐng)求退出   
                }
            }
            else if((Index-WAIT_OBJECT_0)==1)
            {
                return ;
            }
        }
        else
        {
            //取下一個(gè)結(jié)點(diǎn),并發(fā)送
            MSG_NODE p=pNetClient->RecvMsgQueue.DeQueue();
            //釋放隊(duì)列
            ::LeaveCriticalSection(&pNetClient->RecvMsgQueSection);
            //調(diào)用回調(diào)函數(shù),處理數(shù)據(jù)
            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 ;//應(yīng)用程序請(qǐng)求退出   
            }
            //連接已經(jīng)被斷開(kāi),通知上層(通過(guò)調(diào)用回調(diào)函數(shù))
            m_pProcessRecvClientData(NULL,0, m_pProcessRecvContext);
            //pNetClient->UnInit();
            return ;
        }
        else
        {
            if(bOprUnInit)
            {
                return ;//應(yīng)用程序請(qǐng)求退出   
            }
            //沒(méi)收到字節(jié)?還是出錯(cuò)
            if(retlen==0 || retlen > BUFFER_SIZE)
            {
                m_pProcessRecvClientData(NULL,0, m_pProcessRecvContext);
                //pNetClient->UnInit();
                return ;
            }
            //將接收到的數(shù)據(jù)放到接收隊(duì)列里
            MSG_NODE Msg;
            Msg.DataLength=retlen;
            memcpy(Msg.pData,RecvBuf,retlen);

            //插入消息隊(duì)列
            ::EnterCriticalSection(&RecvMsgQueSection);
            if(RecvMsgQueue.IsEmpty())
            {
                RecvMsgQueue.EnQueue(Msg);
                ::LeaveCriticalSection(&RecvMsgQueSection);
                //如果消息隊(duì)列為空,告訴工作線程可以進(jìn)行工作了
                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 //回調(diào)函數(shù)空
        || szSvrAddr==NULL //地址空
        || IsStart)//已經(jīng)啟動(dòng)過(guò)了
    {
        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;
        }
    }
    //啟動(dòng)工作線程,并升高工作線程的等級(jí)至最高
    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);
    }
    //啟動(dòng)接收線程
    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);//退出先前創(chuàng)建的線程
            return Error;
        }
    }
    //啟動(dòng)發(fā)送線程
    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);//退出先前創(chuàng)建的線程
            return Error;
        }
    }
    return Error;
}
bool CNetClient::SendMsg(char * pData,unsigned long DataLength)
{       
        //未調(diào)用初始化函數(shù)
        if(!IsStart || pData==NULL || DataLength==0)return false;
        //構(gòu)造消息
        MSG_NODE Msg;
        Msg.DataLength=DataLength;
        memcpy(Msg.pData,pData,DataLength);
        //插入消息隊(duì)列
        ::EnterCriticalSection(&SendMsgQueSection);
        if(SendMsgQueue.IsEmpty())
        {
            SendMsgQueue.EnQueue(Msg);
            ::LeaveCriticalSection(&SendMsgQueSection);
            //如果消息隊(duì)列為空,告訴等待的發(fā)送線程可以發(fā)送了
            SetEvent(hSendEvent);
        }
        else
        {
            SendMsgQueue.EnQueue(Msg);
            ::LeaveCriticalSection(&SendMsgQueSection);
        }
        return true;
}
void CNetClient::WriteLogString(LPCTSTR strLog)
{
    return;
}
/********************************************************************
函數(shù)名  : Queue<T>::~Queue()
輸入?yún)?shù):
輸出參數(shù):
功能描述: 隊(duì)列析構(gòu)函靈敏,清空所有隊(duì)列元素
全局變量: 無(wú)
調(diào)用模塊:
附加說(shuō)明:
********************************************************************/
template <class T>  Queue<T>::~Queue()
{
    QueueNode<T> *p=front;
    while(front!=NULL)
    {
        p=front;
        front=front->link;
        delete p;
    }
}
/********************************************************************
函數(shù)名  : Queue<T>::EnQueue
輸入?yún)?shù):
const T & item :要插入的結(jié)點(diǎn)的引用
輸出參數(shù):
功能描述: 在隊(duì)列中插入一個(gè)結(jié)點(diǎn)
全局變量: 無(wú)
調(diào)用模塊:
附加說(shuō)明:
********************************************************************/
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);
}
/********************************************************************
函數(shù)名  : Queue<T>::DeQueue()
輸入?yún)?shù):
T  :返回被刪除結(jié)點(diǎn)的值
輸出參數(shù):
功能描述: 從隊(duì)列中取出一個(gè)結(jié)點(diǎn),并返回該結(jié)點(diǎn)的值
全局變量: 無(wú)
調(diào)用模塊:
附加說(shuō)明:
********************************************************************/
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;
}
/********************************************************************
函數(shù)名  : Queue<T>::MakeEmpty()
輸入?yún)?shù):
輸出參數(shù):
功能描述: 將隊(duì)列元素清空
全局變量: 無(wú)
調(diào)用模塊:
附加說(shuō)明:
********************************************************************/
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; //設(shè)置發(fā)送超時(shí)6秒
        if(::setsockopt(*pNewSocket,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
            return 0;
        }
        TimeOut=10000;//設(shè)置接收超時(shí)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);
    //設(shè)置非阻塞方式連接
    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 模型,即設(shè)置超時(shí)
    struct timeval timeout ;
    fd_set r;

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

    //一般非鎖定模式套接比較難控制,可以根據(jù)實(shí)際情況考慮 再設(shè)回阻塞模式
    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 閱讀(440) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 代碼片段分享

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲视频 欧洲视频| 一本久久综合亚洲鲁鲁五月天| 亚洲激情第一页| 香蕉成人伊视频在线观看| 久久久久久久高潮| 一区二区三区精品视频| 欧美午夜精品理论片a级按摩| 国产精品每日更新| 亚洲精品中文字幕在线观看| 在线观看亚洲精品视频| 欧美成人午夜激情在线| 亚洲精品少妇30p| 99热这里只有精品8| 一区二区久久久久| 中国女人久久久| 亚洲最新合集| 日韩图片一区| 欧美日在线观看| 亚洲免费影院| 欧美在线资源| 亚洲精品视频免费在线观看| 亚洲乱码国产乱码精品精| 亚洲精品一区中文| 亚洲美女在线国产| 亚洲一区二区免费在线| 亚洲欧美日韩天堂一区二区| 亚洲免费观看| 欧美国产在线观看| 国产精品视频最多的网站| 国产精品久久一级| 99视频在线观看一区三区| 一区二区三区视频观看| 免费亚洲一区二区| 久久精品国产亚洲aⅴ| 久久精品久久综合| 亚洲一区在线看| 一区二区三区国产盗摄| 夜夜嗨网站十八久久| 亚洲摸下面视频| 亚洲国产二区| 在线亚洲+欧美+日本专区| 久久久另类综合| 亚洲免费在线| 亚洲电影免费观看高清| 亚洲天堂av在线免费观看| 欧美承认网站| 欧美日韩在线一区二区| 日韩亚洲精品视频| 亚洲国产日韩美| 欧美日韩一区二区视频在线观看| 亚洲深夜福利| 久久国产直播| 91久久香蕉国产日韩欧美9色 | 亚洲视频观看| 国产精品热久久久久夜色精品三区 | 久久精品国产99国产精品澳门| 亚洲精品视频免费| 欧美午夜理伦三级在线观看| 校园激情久久| 久久国产精品一区二区| 永久555www成人免费| 黑人一区二区三区四区五区| 国产揄拍国内精品对白| 一区二区欧美精品| 免费一级欧美片在线播放| 男男成人高潮片免费网站| 欧美激情国产精品| 性欧美在线看片a免费观看| 欧美精品不卡| 欧美日韩亚洲综合在线| 亚洲国产成人久久综合| 久久不射中文字幕| 亚洲精品一区二区三区樱花| 久久精品123| 一区二区高清在线观看| 欧美成人小视频| 激情久久中文字幕| 久久精品国产亚洲a| 亚洲欧美国内爽妇网| 久久九九全国免费精品观看| 国产欧美日韩| 91久久黄色| 欧美在线播放| 国产精品一区二区久久| 亚洲高清免费在线| 欧美成人高清| 蜜桃av一区二区| **欧美日韩vr在线| 亚洲综合视频一区| 欧美一区二区三区视频免费| 国产日韩欧美不卡在线| 欧美成人自拍| 欧美日韩成人在线视频| 中文一区二区| 久久精品人人| 亚洲另类春色国产| 一本色道精品久久一区二区三区 | 欧美成人精品三级在线观看| 欧美国产成人在线| 日韩网站在线| 亚洲午夜精品一区二区三区他趣 | 欧美全黄视频| 午夜国产精品影院在线观看| 亚洲综合久久久久| 影视先锋久久| 亚洲精品日韩一| 国产精品自拍网站| 亚洲一区二区三区在线看| 亚洲一区日韩在线| 国产亚洲成av人在线观看导航| 久久精品视频在线播放| 免费观看成人| 亚洲性夜色噜噜噜7777| 午夜精品久久久久久久白皮肤| 狠狠色丁香久久综合频道| 久久国产精品久久精品国产| 久久夜色精品亚洲噜噜国产mv| 日韩视频免费大全中文字幕| 一二三四社区欧美黄| 狠狠噜噜久久| 一区二区三区av| 亚洲成人在线视频播放| 欧美成人午夜激情在线| 国产精品成人v| 欧美高清视频免费观看| 国产精品国产三级国产aⅴ浪潮| 久久精品72免费观看| 欧美96在线丨欧| 久久国产精品久久久久久久久久| 欧美高清日韩| 久久久久久尹人网香蕉| 欧美三级乱码| 欧美激情中文字幕在线| 国产一区二区三区av电影 | 久久成人羞羞网站| 欧美紧缚bdsm在线视频| 欧美激情视频在线播放| 亚洲人成人一区二区三区| 亚洲精品一区在线观看香蕉| 欧美一区在线视频| 亚洲欧美综合v| 亚洲男人影院| 久久国产精品久久久久久久久久| 亚洲一区制服诱惑| 亚洲综合色婷婷| 欧美在线视频导航| 欧美在线91| 免费高清在线一区| 欧美福利电影在线观看| 亚洲综合成人婷婷小说| 亚洲婷婷免费| 国产精品久久久久久久久久ktv| 亚洲人www| 夜夜嗨av一区二区三区免费区| 欧美精品久久99| 亚洲人成亚洲人成在线观看图片 | 在线电影国产精品| 老鸭窝91久久精品色噜噜导演| 欧美aⅴ99久久黑人专区| 最新日韩在线| 国产精品二区影院| 久久大综合网| 亚洲三级观看| 久久精品女人| 亚洲美女色禁图| 欧美日韩亚洲一区二区三区四区 | 99国产精品久久久久老师| 在线一区二区日韩| 国产亚洲欧美一区在线观看| 欧美一区二区视频97| 猫咪成人在线观看| 99国产一区| 国产日韩精品在线观看| 久久九九精品99国产精品| 亚洲人成毛片在线播放| 欧美一进一出视频| 亚洲欧洲日本专区| 国产伦精品一区二区三区视频孕妇 | 久久这里有精品15一区二区三区| 亚洲精品国产精品国自产观看| 国产精品乱码一区二三区小蝌蚪| 久久中文在线| 亚洲欧美日本另类| 亚洲三级影院| 欧美高清视频在线播放| 羞羞答答国产精品www一本| 亚洲国产精品综合| 国产精品美女久久久久久免费 | 欧美chengren| 午夜精品久久久久久久| 在线观看免费视频综合| 国产精品久久久爽爽爽麻豆色哟哟 | 一区二区欧美日韩| 久久精品日韩欧美| 中文欧美字幕免费| 亚洲国产成人久久综合一区| 欧美日韩福利在线观看| 六月婷婷一区| 亚洲一区二区三区四区视频| 亚洲人成网站影音先锋播放|