Esempio n. 1
0
// 创建 Listen Socket,进入监听状态,等待客户端的连接
bool CServer::Host(UINT dwPort, const char* strIP,long lFlag, ulong nSocketType)
{
    if(!(m_bMode&2))	return FALSE;

    SetFlag(lFlag);

    // 创建 socket
    bool bRet = CreateEx(dwPort, strIP,nSocketType);
    //创建失败
    if(!bRet)
    {
        return bRet;
    }

    //创建接收客户socket线程
    bRet=CreateAcceptThread();
    if(!bRet)
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"创建接受连接线程失败!");

        return FALSE;
    }

    // listen
    bRet = Listen(m_lMaxBlockConnetNum);
    if(!bRet)
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"listen 失败!");
        return FALSE;
    }
    return bRet;
}
//**********************************
//获得完成端口上收到的数据
//**********************************
bool CServerClient::ReadFromCompletionPort(PER_IO_OPERATION_DATA* pIOData,CDataBlock *pDB)
{	
    if(NULL == pIOData ) return false;
    if(NULL == pDB)
        pDB = m_pDBAllocator->AllocDB(8);
    if(NULL == pDB)
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"在函数CServerClient::ReadFromCompletionPort(...)中,分配内存失败!");
        return false;
    }

    memset( &pIOData->OverLapped,0,sizeof(OVERLAPPED) );
    if(pIOData->m_lDataBufNum < 1)
        pIOData->ResetDataBufSize(1);
    pIOData->pParam = pDB;
    pIOData->pDataBuf[0].len = pDB->GetMaxSize();
    pIOData->pDataBuf[0].buf = (char*)pDB->Base();
    pIOData->OperationType = SOT_Receive;
    pIOData->m_nSequenceNumber = m_ReadSequenceNumber;
    ulong dwFlag = 0;
    ulong dwReceivByte;
    int nRet = WSARecv(m_hSocket,pIOData->pDataBuf,1,&dwReceivByte,&dwFlag,&(pIOData->OverLapped),NULL);
    if(nRet == SOCKET_ERROR)
    {
        int nError = WSAGetLastError();
        if (nError != WSA_IO_PENDING)
        {
            m_pDBAllocator->FreeDB(pDB);
            PutErrorString(NET_MODULE,"%-15s 在函数CServerClient::ReadFromCompletionPort(...)中,WSARecv()操作失败!(ErrorID:%d)",__FUNCTION__,nError);
            return false;
        }
    }
    IncrReadSequenceNumber();
    return true;
}
Esempio n. 3
0
long CServer::Connect(CServerClient* pConClient,LPCTSTR lpszHostAddress, UINT nHostPort,ulong dwTimeOut)
{
    if(NULL == pConClient || NULL == pConClient->m_hSocket)	return FALSE;

    //设置连接的服务器IP和端口
    pConClient->SetPeerIP(lpszHostAddress);
    pConClient->SetPeerPort(nHostPort);

    SOCKADDR_IN sockAddr;
    memset(&sockAddr,0,sizeof(sockAddr));
    LPSTR lpszAscii = (LPTSTR)lpszHostAddress;
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
    if (sockAddr.sin_addr.s_addr == INADDR_NONE)
    {
        PutErrorString(NET_MODULE,"%-15s Given address %s:%u is INVALID, ERR_ID: %d.",__FUNCTION__, lpszHostAddress, nHostPort, GetLastError());
        return FALSE;
    }

    sockAddr.sin_port = htons((u_short)nHostPort);
    if (IsEncryptType(pConClient->GetFlag()))
    {
        pConClient->SetKey(sockAddr.sin_addr.s_addr, sockAddr.sin_port);
    }

    int ret = connect(pConClient->m_hSocket,(SOCKADDR*)&sockAddr, sizeof(sockAddr));
    if( ret == SOCKET_ERROR )
    {
        ulong dwError = WSAGetLastError();
        if(  dwError != WSAEWOULDBLOCK )
        {
            return FALSE;
        }

        //等候一段时间,用是否可写来判断连接成功与否
        fd_set writefd;
        FD_ZERO(&writefd);
        FD_SET(pConClient->m_hSocket,&writefd);
        timeval waittime = {dwTimeOut/1000,(dwTimeOut%1000)*1000};
        int nRet = select(0,NULL,&writefd,NULL,&waittime);
        if(nRet == 0 || nRet == SOCKET_ERROR)
        {
            PutErrorString(NET_MODULE,"%-15s Select %s:%u FAILED, ERR_ID: %d.",__FUNCTION__, lpszHostAddress, nHostPort, WSAGetLastError());
            return FALSE;
        }
    }
    return	TRUE;
}
Esempio n. 4
0
//网络主线程,对网络的操作命令进行解析,执行
unsigned __stdcall NetThreadFunc(void* pArguments)
{
    CServer* pServer=(CServer*)pArguments;
    if(pServer==NULL)
    {
        _endthreadex( 0 );
        return 0;
    }

#ifndef _DEBUG
    __try
    {
#endif

        DoNetThreadFunc(pServer);

#ifndef _DEBUG
    }
    __except(_Sword3::CrashFilter(GetExceptionInformation(),GetExceptionCode()))
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"********服务器工作线程出错,请查看最新的错误报告文件********");
    }
#endif

    _endthreadex( 0 );
    return 0;
}
Esempio n. 5
0
bool CServer::OnClientInit(CServerClient* pClient)
{
    if(pClient == NULL)	return false;

    long lIndexID = pClient->GetIndexID();


    //绑定套接字到完成端口
    if( !AssociateSocketWithCP(pClient->m_hSocket,lIndexID) )
    {
        pClient->Close();
        FreeClient(pClient);
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"在函数CServer::OnConClientInitial(...)中,AssociateSocketWithCP(...)操作失败.");
        return false;
    }

    if( pClient->StartReadData() == false)
    {
        pClient->Close();
        FreeClient(pClient);
        return false;
    }

    if( pClient->IsAccept() )
        AddNewAcceptSocket(lIndexID);

    //判断接受数据是否超时,超时则关闭改套接字
    DoNewAcceptSocket();
    return true;
}
Esempio n. 6
0
// 用于邦定一个SOCKET到完成端口
bool CServer::AssociateSocketWithCP(SOCKET socket,ulong dwCompletionKey)
{
    if(m_hCompletionPort == NULL)
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"在函数 CServer::AssociateSocketWithCP(...)里操作出错,完成端口句柄无效。");
        return false;
    }
    HANDLE hHanle = CreateIoCompletionPort((HANDLE)socket, m_hCompletionPort, dwCompletionKey, 0);
    if(hHanle == NULL)
    {
        ulong dwErrorID = GetLastError();
        PutErrorString(NET_MODULE,"%-15s在函数 CServer::AssociateSocketWithCP(...)里.邦定一个Socket到完成端口出错(ErrorID:%d)",__FUNCTION__,dwErrorID);
        return false;
    }
    if(hHanle!= m_hCompletionPort)
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"在函数 CServer::AssociateSocketWithCP(...)里操作出错,邦定SOCKET到完成端口的返回值出错。");
        return false;
    }
    return true;
}
//当发送数据流量大于限制流量时,发送0字节数据
//用来在下一个周期中来检测、发送数据
void CServerClient::SendZeroByteData()
{
    if(m_bSendZeroByteData)	return;

    PER_IO_OPERATION_DATA* pPerIOData = m_pServers->AllocIoOper();
    //当分配不出内存时
    if(NULL == pPerIOData) return;
    memset( &pPerIOData->OverLapped,0,sizeof(OVERLAPPED) );
    pPerIOData->OperationType = SOT_SendZeroByte;
    bool bSuccess = PostQueuedCompletionStatus(m_pServers->m_hCompletionPort,0,(ulong)GetIndexID(),(OVERLAPPED*)pPerIOData) ? true : false;
    if( !bSuccess && WSAGetLastError() != ERROR_IO_PENDING )
    {
        PutErrorString(NET_MODULE,"%-15sCServerClient::SendZeroByteData().PostQueuedCompletionStatus .erros(errid:%d).",__FUNCTION__,WSAGetLastError());
        return;
    }
    m_bSendZeroByteData = true;
    return;
}
Esempio n. 8
0
//主动连接服务器,返回该连接的ID
//返回-1,表示失败
long CServer::Connect(LPCTSTR lpszHostAddress, UINT nHostPort,long lFlag,ulong dwTimeOut)
{
    if(!(m_bMode&1))	return -1;

    CServerClient* pConClient = AllocClient(false);
    if(pConClient == NULL)	return -1;

    if( !pConClient->CreateEx(0,NULL,SOCK_STREAM) )
    {
        PutErrorString(NET_MODULE,"%-15s Create socket bound to %s:%u FAILED, ERR_ID: %d.",__FUNCTION__, lpszHostAddress, nHostPort, GetLastError());
        return -1;
    }

    pConClient->SetFlag(lFlag);
    //设置编号
    pConClient->SetSendRevBuf();
    //设置套接字选项
    pConClient->SetSocketOpt();

    long lID = pConClient->GetIndexID();

    pConClient->SetClose(false);
    pConClient->SetShutDown(false);

    pConClient->SetParam(false,0xFFFFFFF,m_lConMaxBlockSendMsgNum,
                         m_lConPendingWrBufNum,m_lConPendingRdBufNum,
                         m_lConMaxSendSizePerSecond,m_lConMaxRecvSizePerSecond,lFlag);

    if( !Connect(pConClient,lpszHostAddress,nHostPort,dwTimeOut) )
    {
        pConClient->Close();
        FreeClient(pConClient);
        return -1;
    }

    tagSocketOper* pSocketOpera = AllocSockOper();
    pSocketOpera->Init(SCOT_Init,lID,pConClient,0);
    m_SocketOperaCommands.Push_Back(pSocketOpera);

    return lID;
}
Esempio n. 9
0
//启动网络服务器
//bMode启动模式,1:以客户端的方式启动,2:以服务器的方式启动
bool	CServer::Start(BYTE bMode,CDataBlockAllocator* pDBAllocator,
                       long nMaxFreeSockOperNum,long nMaxFreeIOOperNum,long lIOOperDataBufNum,
                       bool bCheck,long lForbidTime,
                       long lMaxMsgLen,long lMaxConNums,long lTotalClientsNum,
                       long lPendingWrBufNum,long lPendingRdBufNum,
                       long lMaxSendSizePerSecond,long lMaxRecvSizePerSecond,
                       long lMaxBlockSendMsgNum,
                       long lConPendingWrBufNum,long lConPendingRdBufNum,
                       long lConMaxSendSizePerSecond,long lConMaxRecvSizePerSecond,
                       long lConMaxBlockSendMsgNum)
{
    m_bMode = bMode;
    m_pDBAllocator=pDBAllocator;
    m_nMaxFreeSockOperNum = nMaxFreeSockOperNum;
    m_nMaxFreeIOOperNum = nMaxFreeIOOperNum;
    m_lIOOperDataBufNum = lIOOperDataBufNum;

    m_bCheck = bCheck;
    m_lForbidTime = lForbidTime;
    m_lMaxMessageLength=lMaxMsgLen;
    m_lMaxClientConNum = lMaxConNums;
    m_lTotalClientsNum = lTotalClientsNum;
    m_lPendingWrBufNum = lPendingWrBufNum;
    m_lPendingRdBufNum=lPendingRdBufNum;
    m_lMaxSendSizePerSecond = lMaxSendSizePerSecond;
    m_lMaxRecvSizePerSecond = lMaxRecvSizePerSecond;
    m_lMaxBlockSendMsgNum = lMaxBlockSendMsgNum;
    m_lConPendingWrBufNum = lConPendingWrBufNum;
    m_lConPendingRdBufNum=lConPendingRdBufNum;
    m_lConMaxSendSizePerSecond= lConMaxSendSizePerSecond;
    m_lConMaxRecvSizePerSecond = lConMaxRecvSizePerSecond;
    m_lConMaxBlockSendMsgNum = lConMaxBlockSendMsgNum;
    //预分配命令操作结构
    InitializeCriticalSection(&m_CSSockOper);
    InitializeCriticalSection(&m_CSMsgStat);

    uint i = 0;
    for(; i<m_nMaxFreeSockOperNum; i++)
    {
        tagSocketOper* pSockOper = new tagSocketOper();
        m_FreeSocketOpers.push_back(pSockOper);
    }
    //预分配IO操作结构
    InitializeCriticalSection(&m_CSIOOper);
    i = 0;
    for(; i<m_nMaxFreeIOOperNum; i++)
    {
        PER_IO_OPERATION_DATA* pPerIOData  = new PER_IO_OPERATION_DATA(m_lIOOperDataBufNum);
        m_FreeListIOOpers.push_back(pPerIOData);
    }

    //初始化预分配的客户端
    InitClients();


    //得到CPU的数量
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);

    //根据cpu数量创建完成端口
    m_hCompletionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,sysInfo.dwNumberOfProcessors);

    //创建完成端口失败
    if(m_hCompletionPort==NULL)
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"创建完成端口失败!");
        return false;
    }

    //创建网络主线程
    bool bRet = CreateNetMainThread();
    if(!bRet)
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"创建网络主线程失败!");
        return false;
    }

    //创建在完成端口上等待的工作者线程
    bRet=CreateWorkerThreads(sysInfo.dwNumberOfProcessors);
    if(!bRet)
    {
        PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"创建工作线程失败!");
        return false;
    }
    //客户端方式启动
    if(bMode&0x1)
    {
    }
    //服务器方式启动
    if(bMode&0x2)
    {
        //Host(dwPort,strIP,nSocketType);
    }

    //设置本机IP
    SetHostName();
    return true;
}
Esempio n. 10
0
void DoWorkerThreadFunc(CServer* pServer)
{
    bool bResult;//completion port packet flag
    ulong dwNumRead;//bytes num be readed
    ULONG CPDataKey;
    LPER_IO_OPERATION_DATA lpPerIOData;

    char strTempt[100]="";
    while(true)
    {
        //pServer->IncWorkThreadTick();
        //等待完成端口通告
        dwNumRead = -1;
        bResult=GetQueuedCompletionStatus(pServer->m_hCompletionPort,
                                          &dwNumRead,
                                          &CPDataKey,
                                          (LPOVERLAPPED*)&lpPerIOData,
                                          INFINITE)
                ? true : false;

        if(!bResult)
        {
            if(lpPerIOData == NULL && dwNumRead == -1)
            {
                PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__, "完成端口线程产生错误,未取到完成包(bResult == false,lpPerIOData == NULL,ErrorID:%d)。",GetLastError());
            }
            else if(lpPerIOData)
            {
                ulong dwError = GetLastError();
                //添加一个删除Client的操作命令
                tagSocketOper *pSocketOper = pServer->AllocSockOper();
                pSocketOper->Init(SCOT_OnError,CPDataKey,(void*)lpPerIOData,dwError);
                pServer->m_SocketOperaCommands.Push_Back(pSocketOper);
            }
            else
            {
                PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"完成端口线程产生未知错误!");
            }
        }
        else  ////data is valid,dispose!
        {
            //退出
            if(CPDataKey==0)
            {
                break;
            }
            else if(lpPerIOData == NULL)
            {
                PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"完成端口线程产生错误(bResult == true,lpPerIOData == NULL)!");
            }
            else
            {
                tagSocketOper *pSocketOper = pServer->AllocSockOper();
                if(lpPerIOData->OperationType == SOT_SendZeroByte)
                {
                    //如果是发送0字节大小的操作
                    //添加一个删除Client的操作命令
                    pSocketOper->Init(SCOT_OnSendZeroByte,CPDataKey,(void*)lpPerIOData,0);
                }
                else if(dwNumRead==0)
                {
                    //添加一个删除Client的操作命令
                    pSocketOper->Init(SCOT_OnClose,CPDataKey,(void*)lpPerIOData,0);
                }
                else if(lpPerIOData->OperationType == SOT_Receive)
                {
                    pSocketOper->Init(SCOT_OnRecieve,CPDataKey,(void*)lpPerIOData,dwNumRead);
                }
                else if(lpPerIOData->OperationType == SOT_Send)
                {
                    //添加一个完成发送的消息
                    pSocketOper->Init(SCOT_OnSend,CPDataKey,(void*)lpPerIOData,dwNumRead);
                }
                pServer->m_SocketOperaCommands.Push_Back(pSocketOper);
            }
        }
    }
}
Esempio n. 11
0
bool CServerClient::AddSendMsg(CBaseMessage* pMsg)
{
    char strInfo[256]="";
    if(NULL == pMsg)	return false;
    if( IsShutDown() )
    {
        if(pMsg->RemoveRefCount() == 0)
            CBaseMessage::FreeMsg(pMsg);
        return false;
    }
    //如果阻塞的消息数量大于规定数量,则强制性断开该连接
    if(m_SendMessages.size() > m_lMaxBlockSendMsnNum)
    {
        ShutDown();
        if(pMsg->RemoveRefCount() == 0)
        {
            CBaseMessage::FreeMsg(pMsg);
        }
        PutErrorString(NET_MODULE,"%-15s the blocked send messge count(num:%d) greater the max count(num:%d)",
            __FUNCTION__,m_SendMessages.size(),m_lMaxBlockSendMsnNum);

        return false;
    }

    //OnTransferChange();
    //ulong dwCurTime = timeGetTime();
    //long lCurMsgPri = pMsg->GetPriorityValue(dwCurTime);
    ////该消息类型是否可以丢弃
    //bool bDiscard = CBaseMessage::GetIsDiscard(pMsg->GetType());
    ////进行优先级判断,确定插入的位置
    //itMsg it  = m_SendMessages.begin();
    //for(;it != m_SendMessages.end();)
    //{
    //	CBaseMessage* pTemptMsg = (*it);
    //	//如果消息类型一样,查看是否可以丢弃已存在的消息
    //	if(pMsg->GetType() == pTemptMsg->GetType())
    //	{
    //		//如果丢弃标记一样,则丢弃已经存在的消息
    //		if(bDiscard && pMsg->IsDiscardFlagEqual(pTemptMsg) )
    //		{
    //			//_snprintf(strInfo,256,"Discard a messge(type:%d)",pTemptMsg->GetType());
    //			//PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,strInfo);
    //			it = m_SendMessages.erase(it);
    //			CBaseMessage::FreeMsg(pTemptMsg);
    //			continue;
    //		}
    //	}
    //	//类型不一样,判断优先级
    //	else
    //	{
    //		if( lCurMsgPri > pTemptMsg->GetPriorityValue(dwCurTime))
    //		{
    //			_snprintf(strInfo,256,"the messge(type:%d) prio greater the msg(type:%d)",
    //						pMsg->GetType(),pTemptMsg->GetType());
    //			PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,strInfo);
    //			break;
    //		}
    //	}
    //	it++;
    //}
    //
    //m_SendMessages.insert(it,pMsg);
    m_SendMessages.push_back(pMsg);
    //如果已发送的数据小于设置大小,则发送数据
    if( !Send(NULL,0,0) )
        return false;
    return true;
}
Esempio n. 12
0
int CServerClient::Send(CBaseMessage *pMsg,int nFlags)
{
    if(NULL == pMsg)	return false;

    //添加发送消息统计
    //m_pServers->AddSendMsgStat(pMsg->GetType(),pMsg->GetSize());

    PER_IO_OPERATION_DATA* pPerIOData = m_pServers->AllocIoOper();
    //当分配不出内存时
    if(NULL == pPerIOData) return false;
    long lTotalSendSize = 0, lTotalMsgSize = pMsg->GetTotalSize();
    if (m_pServers->IsEncryptType(GetFlag()))
    {
        pMsg->Encrypt(m_kn);
    }

    memset( &pPerIOData->OverLapped,0,sizeof(OVERLAPPED) );		
    pPerIOData->OperationType = SOT_Send;
    pPerIOData->pParam = pMsg;
    pPerIOData->hSocket = m_hSocket;

    vector<CDataBlock*>& DataBlocks = pMsg->GetMsgData();
    long lBlockSize = (long)DataBlocks.size();
    if(pPerIOData->m_lDataBufNum < lBlockSize)
        pPerIOData->ResetDataBufSize(lBlockSize);
    int i = 0;
    for(;i<lBlockSize;i++)
    {
        CDataBlock* pDB = DataBlocks[i];
        pPerIOData->pDataBuf[i].buf=(char*)pDB->Base();
        pPerIOData->pDataBuf[i].len = pDB->GetCurSize();
        lTotalSendSize += pDB->GetCurSize();
    }

    //错误
    if (lTotalSendSize != lTotalMsgSize)
    {
        free(pPerIOData);		
        PutErrorString(NET_MODULE,"%-15s Msg Length Error(NetFlag:%d,IndexID:%d,BlockSize:%d,MsgType:%d,MsgSize:%d,SendSize:%d)",
            __FUNCTION__,GetIndexID(),lBlockSize,pMsg->GetType(),pMsg->GetTotalSize(),lTotalSendSize);
        if(pMsg->RemoveRefCount() == 0)
            CBaseMessage::FreeMsg(pMsg);
        return true;
    }

    ulong dwSentNum = 0;
    int ret = WSASend(m_hSocket, pPerIOData->pDataBuf, lBlockSize, &dwSentNum, nFlags,
        (OVERLAPPED*)pPerIOData, NULL);

    if (ret == SOCKET_ERROR)
    {
        int nError = WSAGetLastError();
        if ( nError != WSA_IO_PENDING)
        {
            free(pPerIOData);
            PutErrorString(NET_MODULE,"%-15s 向客户端发送消息错误(errorID:%d)",__FUNCTION__,nError);
            return false;
        }
    }

    AddSendSize(lTotalSendSize);
    IncPendingWrBufNum(lTotalSendSize);
    return true;
}