// 创建 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; }
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; }
//网络主线程,对网络的操作命令进行解析,执行 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; }
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; }
// 用于邦定一个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; }
//主动连接服务器,返回该连接的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; }
//启动网络服务器 //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; }
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); } } } }
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; }
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; }