bool MightyTCPCompletionPortServer::SendData(const char *pData, int nLen, const string & strLinkNo) { PCompletionPortIOObject sendHandle=NULL; PCompletionPort_BufObj pSendBufRole=NULL; //map<string,PCompletionPortIOObject>::iterator leftPos,rightPos; //leftPos=m_ActiveSocketMap.begin(); //rightPos=m_ActiveSocketMap.end(); sendHandle=SearchSocketObj(strLinkNo); if (sendHandle!=NULL) { pSendBufRole=AllocateBuffer(sendHandle,nLen); if (pSendBufRole) { pSendBufRole->nLen = nLen; memcpy(pSendBufRole->buff,pData, nLen); PostSend(pSendBufRole); return true; } } return false; }
bool IocpTransmitStrategy::HandleSendSuccess(const IocpOperation* iocpOperation , DWORD byteNumber) { MZ_ASSERT_TRUE(&m_sendOperation == iocpOperation); auto& socketBuffer = m_transmitSocket.TheSocketBuffer(); const auto planLength = socketBuffer.m_sendPlan.GetCurLength(); const auto cacheLength = socketBuffer.m_sendCache.GetCurLength(); //NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Send: plan[%d] cache[%d]. [%s:%d]\n", planLength, cacheLength, __FILE__, __LINE__); if (byteNumber == 0) { NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Info: socket close. [%s:%d]\n", __FILE__, __LINE__); m_transmitSocket.Close(); return true; } const auto sendData = nullptr; const auto sendLength = byteNumber; m_transmitSocket.OnSended(sendData, sendLength); const auto restLength = socketBuffer.PreserveSendPlan(byteNumber); MZ_UNUSED_VARIABLE(restLength); return PostSend(); }
int CNTReader::SendCommand(const byte *sbuff,short slen,unsigned char * rbuff,short *rlen,int timeout) { unsigned char sCmd[512]= {0},sResp[512]= {0}; int nCmdLen=0; if(!IsOpen()) return PORT_NOTOPEN_ERROR; sCmd[0]=0x02; sCmd[1]=slen/256; sCmd[2]=slen%256; memcpy(sCmd+3,sbuff,slen); nCmdLen=3+slen; sCmd[nCmdLen]=XOR(sbuff,slen); nCmdLen++; sCmd[nCmdLen]=0x03; nCmdLen++; if( !PostSend(sCmd,nCmdLen,timeout)) { return SEND_DATA_ERROR; } //Sleep(80); if( !PostRecv(sResp,sizeof(sResp),timeout)) { return RECV_DATA_ERROR; } //Resp:数据长度(2字节)+状态码(2字节)+数据 *rlen=sResp[0]*256+sResp[1]-2; //去掉2字节状态码 if(*rlen>256) *rlen=256; if(*rlen>0) memcpy(rbuff,sResp+4,*rlen); return sResp[2]*256+sResp[3]; }
void EasyIocp::PushToDebug(CompTransmitKey *transKey) { sockaddr_in serverAddr, clientAddr; char data[EASYIOCP_MAX_BUFF]; const char *operType; DWORD len; transKey->GetBothAddr(&serverAddr, &clientAddr); EasyIocpBuffer *iocpBuffer = transKey->GetBuffer(); len = iocpBuffer->GetBody(data, EASYIOCP_MAX_BUFF); data[len] = 0; if(transKey->GetOperType() == operRecv) { operType = "recv"; print("%s:%d %s from %s:%d, data: %s", inet_ntoa(serverAddr.sin_addr), ntohs(serverAddr.sin_port), operType, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port), data); PostSend(transKey->GetSocket(), data, len); } else if(transKey->GetOperType() == operSend) { /*operType = "send"; print("%s:%d %s to %s:%d, data:%s", inet_ntoa(serverAddr.sin_addr), ntohs(serverAddr.sin_port), operType, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port), data);*/ PostRecv(transKey); } else { print("EasyIocp::PushToDebug: invalid oper."); } }
BOOL CIOCPServer::SendText(CIOCPContext *pContext, char *pszText, int nLen) { CIOCPBuffer *pBuffer = AllocateBuffer(nLen); if(pBuffer != NULL) { memcpy(pBuffer->buff, pszText, nLen); return PostSend(pContext, pBuffer); } return FALSE; }
///函数:投递一个send请求。 bool EasyIocp::PostSend(SOCKET transSock, char *data, int len) { CompTransmitKey *transKey = easyClients_.FindClient(transSock); if(!transKey) return false; EasyIocpBuffer *iocpBuffer = transKey->GetBuffer(); iocpBuffer->SetBody(data, len); return PostSend(transKey); }
BOOL CIOCPServer::SendText(CIOCPContext *pContext, char *pszText, int nLen) { CIOCPBuffer *pBuffer = AllocateBuffer(nLen); if(pBuffer != NULL) { memcpy(pBuffer->buff, pszText, nLen); if (PostSend(pContext, pBuffer)) return true; ReleaseBuffer(pBuffer); } return false; }
void Session::EchoBack() { size_t len = mRecvBuffer.GetContiguiousBytes(); if (len == 0) return; if (false == PostSend(mRecvBuffer.GetBufferStart(), len)) return; mRecvBuffer.Remove(len); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// \brief /// \param CAsyncTimerEvent * evt /// \return void //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CAsyncPlayer::OnTimer(CAsyncTimerEvent* evt) { SafeGuard(); if (m_PingTimer == evt) { CPacketWriter<PKTEcho> echoPacket; echoPacket->SetStr(_T("Ping")); PostSend(echoPacket); TRACE(_T("Ping send")); } }
void EasyIocp::DoSend(CompTransmitKey *transKey, DWORD transBytes) { EasyIocpBuffer *iocpBuffer = transKey->GetBuffer(); iocpBuffer->AddTransBytes(transBytes); if(iocpBuffer->IsTransComplete()) { //数据发送完毕 //PushToBusiness(transKey); PushToDebug(transKey); }else { PostSend(transKey); //数据未发送完毕,则继续发送 } }
bool Session::SendRequest(BasePacket* pPacket) { IPacketProtocol* pProtocol = GetPacketProtocol(); if (NULL == pProtocol) return false; char* pBuffer = NULL; int bufferSize; if (false == pProtocol->Encode(pPacket, &pBuffer, bufferSize)) return false; PostSend(false, bufferSize, pBuffer); return true; }
bool IocpTransmitStrategy::PostOutput() { if (!m_transmitSocket.IsWorking()) { return false; } if (m_sendOperation.IsBusy()) { return true; } if (!m_transmitSocket.TheSocketBuffer().HasDataToSend()) { return true; } m_sendOperation.SetBusy(true); return PostSend(); }
void NetSocket::PrepareSend() { unsigned int sendPacketSize = 0; MemoryBlock* buffer = nullptr; while (!_sendPendingQueue.empty() && (_sendQueue.unsafe_size() < MAX_SEND_ARRAY_SIZE) && (sendPacketSize < DEF_SOCKET_BUFFER_SIZE)) { _sendPendingQueue.try_pop(buffer); _sendQueue.push(buffer); sendPacketSize += buffer->GetDataLen(); } if (sendPacketSize > 0) PostSend(); }
void Server::Echo(Packet* packet) { assert(packet); assert(packet->GetSender()); CritSecLock lock(m_CSForClients); ClientList::iterator itor = std::find(m_Clients.begin(), m_Clients.end(), packet->GetSender()); if (itor == m_Clients.end()) { // No client to send it back. Packet::Destroy(packet); } else { PostSend(packet->GetSender(), packet); } }
void Session::handle_write(const boost::system::error_code& error, size_t bytes_transferred) { delete[] m_SendDataQueue.front(); m_SendDataQueue.pop_front(); m_SendDataSizeQueue.pop_front(); if( m_SendDataQueue.empty() == false ) { m_bCompletedWrite = false; char* pData = m_SendDataQueue.front(); int nSize = m_SendDataSizeQueue.front(); PostSend(true, nSize, pData); } else { m_bCompletedWrite = true; } }
//接数数据 int CYCTReaderInterface::SendReaderCommand(char *ComPort,unsigned char Cmd,unsigned char *SendData, unsigned char SendDataLen,unsigned char *RetCode, unsigned char *RecvData,unsigned char* RecvDataLen) { char sCmd[256],sResp[256]; int nCmdLen=0; memset(sCmd,0,sizeof sCmd); memset(sResp,0,sizeof sResp); if( !m_bComStatus ) { if( !CPU_Open(m_sCom,57600) ) { RetCode[0]=0x4F; return 1; } } sCmd[0]=(char)0xBA; sCmd[1]=(char)(2+SendDataLen); sCmd[2]=Cmd; memcpy(sCmd+3,SendData,SendDataLen); nCmdLen=3+SendDataLen; sCmd[nCmdLen]=XOR((byte*)sCmd,nCmdLen); nCmdLen++; if( !PostSend(sCmd,nCmdLen,2000) ) { return SEND_DATA_ERROR; } Sleep(80); if( !PostRecv(sResp,sizeof(sResp),2000) ) { return RECV_DATA_ERROR; } *RetCode=sResp[3]; *RecvDataLen=sResp[1]-3; if(*RecvDataLen>0) memcpy(RecvData,sResp+4,*RecvDataLen); return 0; }
BOOL HandleIO(PBUFFER_OBJ pBuffer) { PSOCKET_OBJ pSocket = pBuffer->pSocket; // 从BUFFER_OBJ对象中提取SOCKET_OBJ对象指针,为的是方便引用 pSocket->nOutstandingOps --; DWORD dwTrans; //用于取得实际传输字节的数量 DWORD dwFlags; //用于取得完成状态 // 获取重叠操作结果 true 重叠操作成功 false 套接字上有错误发生 BOOL bRet = ::WSAGetOverlappedResult(pSocket->s, &pBuffer->ol, &dwTrans, FALSE, &dwFlags); if(!bRet) { // 在此套节字上有错误发生,因此,关闭套节字,移除此缓冲区对象。 // 如果没有其它抛出的I/O请求了,释放此缓冲区对象,否则,等待此套节字上的其它I/O也完成 if(pSocket->s != INVALID_SOCKET) { ::closesocket(pSocket->s); pSocket->s = INVALID_SOCKET; } if(pSocket->nOutstandingOps == 0) FreeSocketObj(pSocket); FreeBufferObj(pBuffer); return FALSE; } // 没有错误发生,处理已完成的I/O switch(pBuffer->nOperation) { case OP_ACCEPT: // 接收到一个新的连接,并接收到了对方发来的第一个封包 { // 为新客户创建一个SOCKET_OBJ对象 PSOCKET_OBJ pClient = GetSocketObj(pBuffer->sAccept); // 为收发数据创建一个BUFFER_OBJ对象,这个对象会在套节字出错或者关闭时释放 PBUFFER_OBJ pSend = GetBufferObj(pClient, BUFFER_SIZE); if(pSend == NULL) { printf(" Too much connections! \n"); FreeSocketObj(pClient); return FALSE; } SOCKADDR_IN LocalSockAddr; SOCKADDR_IN RemoteSockAddr; int nLocalLen, nRmoteLen; LPSOCKADDR pLocalAddr, pRemoteAddr; g_pfnGetAcceptExSockaddrs( pBuffer->buff, pBuffer->nLen - ((sizeof(sockaddr_in) + 16) * 2), sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, (SOCKADDR **)&pLocalAddr, &nLocalLen, (SOCKADDR **)&pRemoteAddr, &nRmoteLen); memcpy(&LocalSockAddr, pLocalAddr, nLocalLen); memcpy(&RemoteSockAddr, pRemoteAddr, nRmoteLen); printf("Local Accepted client:%s:%d\n", inet_ntoa(LocalSockAddr.sin_addr), ntohs(LocalSockAddr.sin_port)); printf("Remote Accepted client:%s:%d\n", inet_ntoa(RemoteSockAddr.sin_addr), ntohs(RemoteSockAddr.sin_port)); RebuildArray(); // 将数据复制到发送缓冲区 pSend->nLen = dwTrans; memcpy(pSend->buff, pBuffer->buff, dwTrans); // 投递此发送I/O(将数据回显给客户) if(!PostSend(pSend)) { // 万一出错的话,释放上面刚申请的两个对象 FreeSocketObj(pSocket); FreeBufferObj(pSend); return FALSE; } // 继续投递接受I/O PostAccept(pBuffer); } break; case OP_RECV: // 接收数据完成 { if(dwTrans > 0) { // 创建一个缓冲区,以发送数据。这里就使用原来的缓冲区 PBUFFER_OBJ pSend = pBuffer; printf("收到:%s\r\n", pBuffer->buff); pSend->nLen = dwTrans; // 投递发送I/O(将数据回显给客户) PostSend(pSend); } else // 套节字关闭 { // 必须先关闭套节字,以便在此套节字上投递的其它I/O也返回 if(pSocket->s != INVALID_SOCKET) { ::closesocket(pSocket->s); pSocket->s = INVALID_SOCKET; } if(pSocket->nOutstandingOps == 0) FreeSocketObj(pSocket); FreeBufferObj(pBuffer); return FALSE; } } break; case OP_SEND: // 发送数据完成 { if(dwTrans > 0) { // 继续使用这个缓冲区投递接收数据的请求 pBuffer->nLen = BUFFER_SIZE; PostRecv(pBuffer); } else // 套节字关闭 { // 同样,要先关闭套节字 if(pSocket->s != INVALID_SOCKET) { ::closesocket(pSocket->s); pSocket->s = INVALID_SOCKET; } if(pSocket->nOutstandingOps == 0) FreeSocketObj(pSocket); FreeBufferObj(pBuffer); return FALSE; } } break; } return TRUE; }
int Connections::PushPacket(Packet* pPacket) { FUNCTION_BEGIN(); if (false == IsStatus(CONNSTATUS_ACTIVE)) { return 1;//ERR_NET_CONNECTION_STATUS_WRONG } if (false == pPacket->IsValidPacket()) { return 2;//ERR_NET_PACKET_INVALID } _mutexSend.Lock(); if (pPacket->GetPacketLen() > GetMaxSendPacketSize()) { _mutexSend.Unlock(); return 3;//ERR_NET_PACKET_EXCEED_ALLOWED_SIZE } if (_sendBuffer.GetPushAvailableSize() <= pPacket->GetUsedSize()) { if (false == IsSetControlFlag(CONTROL_FLAG_USE_SEND_QUEUE)) { _mutexSend.Unlock(); return 4;//ERR_NET_SESSION_SEND_BUFFER_OVERFLOW } else { Packet * QueuedPacket = new Packet(*pPacket); if (NULL == QueuedPacket) { _mutexSend.Unlock(); return 5;//ERR_SYS_MEMORY_ALLOC_FAIL } if (false == _sendQueue.PushPacket(QueuedPacket)) { SAFE_DELETE(QueuedPacket); _mutexSend.Unlock(); return 6;//ERR_NET_SESSION_SEND_BUFFER_OVERFLOW; } _mutexSend.Unlock(); return 0; } } memcpy(_sendBuffer.GetQueuePushPtr(), pPacket->GetPacketBuffer(), pPacket->GetUsedSize()); Packet sendPacket(_sendBuffer.GetQueuePushPtr()); BYTE Sequence = (BYTE)(_PacketSendCount & PACKET_MAX_SEQUENCE); SetSequence(sendPacket.GetPacketHeader(), Sequence); int rc = 0; if (_PacketEncoder) { rc = _PacketEncoder->TxEncrypt(sendPacket); if (0 != rc) { _mutexSend.Unlock(); return 7;//ERR_NET_PACKET_ENCRYPT_FAIL } } _sendBuffer.IncreasePushPos(pPacket->GetUsedSize()); IncreasePacketSend(); if (false == _IsSending) { rc = PostSend(); if (0 != rc) { _mutexSend.Unlock(); return rc; } _IsSending = true; } _mutexSend.Unlock(); return 0; }
int Connections::CompleteSend(DWORD TransferedBytes) { UNREFERENCED_PARAMETER(TransferedBytes); FUNCTION_BEGIN(); IncreaseBytesSend(TransferedBytes); _mutexSend.Lock(); _sendBuffer.IncreasePopPos(TransferedBytes); int rc = 0; if (IsSetControlFlag(CONTROL_FLAG_USE_SEND_QUEUE)) { Packet * SendPacket = _sendQueue.PeekPacket(); while (SendPacket) { if (_sendBuffer.GetPushAvailableSize() <= SendPacket->GetUsedSize()) { break; } BYTE Sequence = (BYTE)(_PacketSendCount & PACKET_MAX_SEQUENCE); SetSequence(SendPacket->GetPacketHeader(), Sequence); if (_PacketEncoder) { rc = _PacketEncoder->TxEncrypt(*SendPacket); if (0 != rc) { _mutexSend.Unlock(); Logger::Log("Session[%X] TxEncrypt Error[%d]\n", this, rc); return 1; //ERR_NET_PACKET_ENCRYPT_FAIL } } memcpy(_sendBuffer.GetQueuePushPtr(), SendPacket->GetPacketBuffer(), SendPacket->GetUsedSize()); _sendBuffer.IncreasePushPos(SendPacket->GetUsedSize()); IncreasePacketSend(); _sendQueue.PopPacket(); SAFE_DELETE(SendPacket); SendPacket = _sendQueue.PeekPacket(); } } if (_sendBuffer.GetCurSize()) { rc = PostSend(); if (0 != rc) { _IsSending = false; _mutexSend.Unlock(); Disconnect(false); Logger::Log("Session[%X] PostSend Error[%d]\n", this, rc); return 0; } } else { _IsSending = false; } _mutexSend.Unlock(); return 0; }
//--------------------------------------------------------------------------------------------------------------------------- //HanelIO() //--------------------------------------------------------------------------------------------------------------------------- void CIocpServer::HandleIo(SOCKET_OBJ *sock, BUFFER_OBJ *buf, HANDLE CompPort, DWORD BytesTransfered, DWORD error, ADOConn *pAdo,bool isClient) { #ifdef LOG_STATUS InterlockedDecrement(&gIoCount); #endif switch(buf->operation) { case OP_ACCEPT: //处理AcceptEx的返回 LOCK(&sock->cs);//加锁 { if(error == 0) { SOCKET_OBJ *clientobj = GetSocketObj(buf->sclient);//创建一个客户端sockobj HANDLE hrc = CreateIoCompletionPort( //将sockobj添加到完成端口处理列表 (HANDLE)buf->sclient, CompPort, (ULONG_PTR)clientobj, 0 ); if (hrc != NULL) { //读取ip地址 SOCKADDR *local=NULL; SOCKADDR *remote=NULL; int local_len; int remote_len; lpfnGetAcceptExSockaddrs(buf->buf,0,sizeof(SOCKADDR_STORAGE) + 16 ,sizeof(SOCKADDR_STORAGE) + 16, &local,&local_len,&remote,&remote_len); clientobj->addr = ((SOCKADDR_IN *)remote)->sin_addr; #ifdef LOG_LEVEL1 Log_Server.Write("--新连接 ip = %s , sock = %d ",GetAddress(clientobj), clientobj->s); #endif BUFFER_OBJ *recvobj = GetBufferObj(); //禁用发送缓冲 #ifdef SEND_BUF_DISABLE BOOL sndbuf=0; setsockopt(buf->sclient,SOL_SOCKET,SO_SNDBUF,(char *)&sndbuf,sizeof(sndbuf)); #endif LOCK(&clientobj->cs); if(PostRecv(clientobj,recvobj) == 0) { #ifdef DEBUG_IOCP clientobj->sockfd = clientobj->s; recvobj->sclient = clientobj->s; #endif clientobj->recvobj = recvobj; AddAlive(clientobj,GetTickCount()); //把他添加到心跳列表,如果一个客户端连上来以后不发数据,会被踢掉 } else { FreeBufferObj(recvobj); closesocket(clientobj->s); //注意关闭句柄,clientobj->s的句柄在PostAccept时候创建 clientobj->s = INVALID_SOCKET; FreeSocketObj(clientobj); } UNLOCK(&clientobj->cs); } else { //创建完成端口失败,像new失败一样,基本上不会出现 #ifdef LOG_LEVEL2 Log_Server.Write("CreateIoCompletionPort 错误:%d",GetLastError()); #endif closesocket(clientobj->s); clientobj->s = INVALID_SOCKET; FreeSocketObj(clientobj); } } else //如果AcceptEx返回出错,说明有一个客户端连了一半就退了,需要把他的句柄关了. closesocket(buf->sclient); InterlockedDecrement(&m_accept_count); // 一般情况下重新PostAccept if(m_accept_count < DEFAULT_ACCEPTEX_COUNT *2) { if(PostAccept(sock,buf)!=0) FreeBufferObj(buf); } } UNLOCK(&sock->cs); break; case OP_READ: //收到数据了 { LOCK(&sock->cs); //锁一下 bool bflag = false; _ASSERTE(buf == sock->recvobj); if(error == 0 && BytesTransfered > 0 ) { #ifdef LOG_LEVEL1 char head[256]; sprintf(head,"(%d) :接收",sock->s); if(isClient) strcat(head,"CL"); Log_Server.WriteHex(buf->buf+buf->buflen,BytesTransfered,head,(int)strlen(head)); #endif buf->buflen += BytesTransfered; int nret = 0; if(isClient) { //调用可以重载的虚函数 //开锁,否则在On系列函数中调用Send(),CloseSock()时候会死锁! UNLOCK(&sock->cs); nret = CLOnRead(sock,buf->buf,buf->buflen,sock->flag,pAdo); LOCK(&sock->cs); } else if(sock->flag_accept == 1) { UNLOCK(&sock->cs); nret = OnRead(sock,buf->buf,buf->buflen,pAdo); LOCK(&sock->cs); } else { sock->flag_close = 1; //设置允许标志,否则调用Send将会失败 sock->flag_accept = 1; //设置accept标志 #ifndef ENABLE_KEEPALIVE //没有启用KeepAlive DeleteAlive(sock); #endif #ifdef DEBUG_IOCP sock->freeed = 0; sock->onclosed = 0; #endif UNLOCK(&sock->cs); nret = OnAccept(sock,buf->buf,buf->buflen,pAdo); LOCK(&sock->cs); } _ASSERTE(nret >= 0 && nret <= buf->buflen); if(nret < 0 || nret > buf->buflen) { #ifdef LOG_LEVEL2 Log_Server.Write("指令处理出错啦\n"); nret = buf->buflen; //强制设置为完全处理 #endif } #ifdef ENABLE_KEEPALIVE sock->timeAlive = GetTickCount(); //设置新的心跳时间 #endif buf->buflen -= nret; if(nret > 0 && buf->buflen > 0) memmove(buf->buf,buf->buf+nret,buf->buflen); if(PostRecv(sock,buf) == 0) //重新递交一个接收操作 bflag = true; } if(!bflag) { DeleteClose(sock); //看看是否存在于延时关闭列表中 DeleteAlive(sock); //看看是否存在于心跳列表中 if(sock->s != INVALID_SOCKET) { closesocket(sock->s); sock->s = INVALID_SOCKET; } sock->flag_close = 0; //设置关闭标志 FreeBufferObj(buf); if( sock->flag_accept == 1) { UNLOCK(&sock->cs); if(!isClient) OnClose(sock,pAdo); //调用一次OnClose(),告诉上层的程序,不要再去用这个sock了 else CLOnClose(sock,sock->flag,pAdo); LOCK(&sock->cs); #ifdef DEBUG_IOCP sock->onclosed = 1; //调试时设置关闭标志,用于检测是否存在逻辑问题 #endif } sock->recvobj = NULL; if(sock->recvobj == NULL && sock->sendobj == NULL) { UNLOCK(&sock->cs); FreeSocketObj(sock); //释放该客户端对应的sockobj对象 return; } } UNLOCK(&sock->cs); } break; case OP_WRITE: LOCK(&sock->cs); { _ASSERTE(buf == sock->sendobj); bool bflag = false; BUFFER_OBJ *tmpobj = sock->sendobj; sock->sendobj = sock->sendobj->next; if(error == 0 && BytesTransfered > 0) //前一个发送已经完成 { #ifdef LOG_LEVEL1 char head[256]; sprintf(head,"(%d) :发送",sock->s); if(isClient) strcat(head,"CL"); Log_Server.WriteHex(buf->buf,BytesTransfered,head,(int)strlen(head)); #endif //检查发送队列 if(sock->sendobj == NULL) bflag = true; else if(PostSend(sock,sock->sendobj) == 0) bflag = true; } FreeBufferObj(tmpobj); if(!bflag) { sock->flag_close = 0; //设置关闭标志 while(sock->sendobj) { tmpobj = sock->sendobj; sock->sendobj = sock->sendobj->next; FreeBufferObj(tmpobj); } if(sock->recvobj == NULL && sock->sendobj == NULL) { UNLOCK(&sock->cs); FreeSocketObj(sock); //如果OP_READ时,sock->sendobj!=NULL,那么需要在这里释放客户端的SocketOBJ return; } } } UNLOCK(&sock->cs); break; } }
//如果发送队列存在,Send()首先尝试将数据添加到队列的最后一个BufferOBJ.如果BufferOBJ的可用空间不足, //Send()将开辟一个新的BufferOBJ用于发送.当发送队列为空时,Send()将调用PostSend()立即提交一个发送操作 // int CIocpServer::Send(SOCKET_OBJ *sock,const void * buffer,int len)//发送向客户端数据 { _ASSERTE(len <= DEFAULT_BUFFER_SIZE*MAX_UNSENDS_COUNT && len > 0); if(sock == NULL || len > DEFAULT_BUFFER_SIZE*MAX_UNSENDS_COUNT || len <= 0) return -1; BUFFER_OBJ * tmpbuf; int rc=NO_ERROR; #ifdef DEBUG_IOCP _ASSERTE(sock->onclosed == 0); //已经调用过OnClose()还发? _ASSERTE(sock->freeed == 0); //已经free掉了! #endif InterlockedIncrement(&sock->sending_count); //为了安全的freeobj if( ( sock->flag_close == 0 ) || (sock->s == INVALID_SOCKET) ) { InterlockedDecrement(&sock->sending_count); return -1; } int i=0; int len2=len; char *buf2; if(len2 > DEFAULT_BUFFER_SIZE) len2 = DEFAULT_BUFFER_SIZE; LOCK(&sock->cs); tmpbuf = sock->sendobj; if(tmpbuf == NULL) { //发送队列为空 tmpbuf = GetBufferObj(); #ifdef DEBUG_IOCP tmpbuf->sclient = sock->s; #endif memcpy(tmpbuf->buf,buffer,len2); tmpbuf->buflen = len2; rc = PostSend(sock,tmpbuf); if(rc == 0) sock->sendobj = tmpbuf; else FreeBufferObj(tmpbuf); } else { while(tmpbuf->next) { tmpbuf = tmpbuf->next; i++; } if(i > MAX_UNSENDS_COUNT) { rc = -1; CloseSock(sock); } else { if(tmpbuf->buflen + len2 > DEFAULT_BUFFER_SIZE) { tmpbuf->next = GetBufferObj(); tmpbuf = tmpbuf->next; } memcpy(tmpbuf->buf+tmpbuf->buflen,buffer,len2); tmpbuf->buflen += len2; } } len -= len2; buf2 = (char *)buffer+len2; while(rc == 0 && len >0) { len2 = len; if(len2 > DEFAULT_BUFFER_SIZE) len2 = DEFAULT_BUFFER_SIZE; tmpbuf->next = GetBufferObj(); tmpbuf = tmpbuf->next; memcpy(tmpbuf->buf,buf2,len2); tmpbuf->buflen = len2; len -= len2; buf2 += len2; i++; if(i > MAX_UNSENDS_COUNT) { #ifdef LOG_LEVEL1 Log_Server.Write("Send(): 发送失败(当前用户的发送队列超出 %d!",MAX_UNSENDS_COUNT); #endif rc = -1; break; } } UNLOCK(&sock->cs); InterlockedDecrement(&sock->sending_count); return rc; //注意:在PostSend()里面,buflen被设置为DEFAULT_BUFFER_SIZE,Send()调用时候的数据不会添加到正在发送的BufferObj后面 }
//----------------------------------------------------------------------------------- // Purpose : // Return : //----------------------------------------------------------------------------------- // Called by App TH, Worker TH ( Send ) //----------------------------------------------------------------------------------- int CNtlConnection::PushPacket(CNtlPacket * pPacket) { FUNCTION_BEGIN(); if( false == IsStatus( STATUS_ACTIVE ) ) { return NTL_ERR_NET_CONNECTION_STATUS_WRONG; } if( false == pPacket->IsValidPacket() ) { return NTL_ERR_NET_PACKET_INVALID; } m_mutexSend.Lock(); // ¹ØÀ¸·Î ³»¸®¸é µ¿±âÈ°¡ ±úÁø´Ù [5/30/2008 SGpro] if( pPacket->GetPacketLen() > GetMaxSendPacketSize() ) { m_mutexSend.Unlock(); return NTL_ERR_NET_PACKET_EXCEED_ALLOWED_SIZE; } if( m_sendBuffer.GetPushAvailableSize() <= pPacket->GetUsedSize() ) { if( false == IsSetControlFlag( CONTROL_FLAG_USE_SEND_QUEUE ) ) { m_mutexSend.Unlock(); return NTL_ERR_NET_SESSION_SEND_BUFFER_OVERFLOW; } else { CNtlPacket * pQueuedPacket = new CNtlPacket( *pPacket ); if( NULL == pQueuedPacket ) { m_mutexSend.Unlock(); return NTL_ERR_SYS_MEMORY_ALLOC_FAIL; } if( false == m_sendQueue.PushPacket( pQueuedPacket ) ) { SAFE_DELETE( pQueuedPacket ); m_mutexSend.Unlock(); return NTL_ERR_NET_SESSION_SEND_BUFFER_OVERFLOW; } m_mutexSend.Unlock(); return NTL_SUCCESS; } } //m_mutexSend.Lock(); //¿©±â¿¡ µÎ¸é µ¿±âÈ°¡ ±úÁø´Ù [5/30/2008 SGpro] memcpy( m_sendBuffer.GetQueuePushPtr(), pPacket->GetPacketBuffer(), pPacket->GetUsedSize() ); // [9/10/2007 zeroera] : ¼³¸í : È¿À²¼ºÀ» À§ÇØ ÆÐŶ ¹öÆÛ¿¡ ÀÖ´Â µ¥ÀÌŸ¸¦ °¡Áö°í ¾ÏÈ£È ÇÑ´Ù CNtlPacket sendPacket( m_sendBuffer.GetQueuePushPtr() ); BYTE bySequence = (BYTE) ( m_dwPacketSendCount & PACKET_MAX_SEQUENCE ); SetSequence( sendPacket.GetPacketHeader(), bySequence ); int rc = NTL_SUCCESS; #if __SGPRO_BOTSYSTEM_SENDANDRECVTESTCODE__ #else if( m_pPacketEncoder ) { rc = m_pPacketEncoder->TxEncrypt( sendPacket ); if( NTL_SUCCESS != rc ) { m_mutexSend.Unlock(); return NTL_ERR_NET_PACKET_ENCRYPT_FAIL; } } #endif m_sendBuffer.IncreasePushPos( pPacket->GetUsedSize() ); IncreasePacketSend(); if( false == m_bSending ) { rc = PostSend(); if( NTL_SUCCESS != rc ) { m_mutexSend.Unlock(); return rc; } m_bSending = true; } m_mutexSend.Unlock(); return NTL_SUCCESS; }
//----------------------------------------------------------------------------------- // Purpose : // Return : //----------------------------------------------------------------------------------- // Called by Worker TH ( IOCP ) //----------------------------------------------------------------------------------- int CNtlConnection::CompleteSend(DWORD dwTransferedBytes) { UNREFERENCED_PARAMETER( dwTransferedBytes ); FUNCTION_BEGIN(); IncreaseBytesSend( dwTransferedBytes ); m_mutexSend.Lock(); m_sendBuffer.IncreasePopPos( dwTransferedBytes ); int rc = 0; if( IsSetControlFlag( CONTROL_FLAG_USE_SEND_QUEUE ) ) { CNtlPacket * pSendPacket = m_sendQueue.PeekPacket(); while( pSendPacket ) { if( m_sendBuffer.GetPushAvailableSize() <= pSendPacket->GetUsedSize() ) { break; } BYTE bySequence = (BYTE) ( m_dwPacketSendCount & PACKET_MAX_SEQUENCE ); SetSequence( pSendPacket->GetPacketHeader(), bySequence ); #if __SGPRO_BOTSYSTEM_SENDANDRECVTESTCODE__ #else if( m_pPacketEncoder ) { rc = m_pPacketEncoder->TxEncrypt( *pSendPacket ); if( NTL_SUCCESS != rc ) { m_mutexSend.Unlock(); NTL_LOGDL( LOG_NETWORK, "Session[%X] TxEncrypt Error[%d:%s]", this, rc, NtlGetErrorMessage(rc) ); return NTL_ERR_NET_PACKET_ENCRYPT_FAIL; } } #endif memcpy( m_sendBuffer.GetQueuePushPtr(), pSendPacket->GetPacketBuffer(), pSendPacket->GetUsedSize() ); m_sendBuffer.IncreasePushPos( pSendPacket->GetUsedSize() ); IncreasePacketSend(); m_sendQueue.PopPacket(); SAFE_DELETE( pSendPacket ); pSendPacket = m_sendQueue.PeekPacket(); } } if( m_sendBuffer.GetCurSize() ) { rc = PostSend(); if( NTL_SUCCESS != rc ) { m_bSending = false; m_mutexSend.Unlock(); // [1/20/2007 zeroera] : ¼³¸í : Send¿¡ ÀÇÇÑ Close ±â´ÉÀ» ¸·À½. TH1ÀÌ Recv Áß¿¡ TH2 °¡ Send ÇÏ¿© CloseÇÏ°Ô µÇ¸é ¹®Á¦°¡ ¹ß»ý ÇÒ ¼ÒÁö°¡ ÀÖÀ½ //return rc; Disconnect( false ); NTL_LOGDL( LOG_NETWORK, "Session[%X] PostSend Error[%d:%s]", this, rc, NtlGetErrorMessage(rc) ); return NTL_SUCCESS; } } else { m_bSending = false; } m_mutexSend.Unlock(); //NTL_PRINT(PRINT_SYSTEM, "Session[%X]\tCompleteSend Complete SendBufferSize[%d] TotalSendBytes[%u]", this, m_sendBuffer.GetCurSize(), m_dwTotalSendSize ); return NTL_SUCCESS; }