void CSocketClient::Write( const char *pData, size_t dataLength ) { if ( INVALID_SOCKET != m_connectSocket && dataLength > 0 && pData ) { CIOBuffer *pBuffer = Allocate(); /* * Call to unqualified virtual function */ PreWrite( pBuffer, pData, dataLength ); pBuffer->AddData( pData, dataLength ); /* * Begin to send data */ pBuffer->SetupWrite(); DWORD dwFlags = 0; DWORD dwSendNumBytes = 0; if ( SOCKET_ERROR == ::WSASend( m_connectSocket, pBuffer->GetWSABUF(), 1, &dwSendNumBytes, dwFlags, pBuffer, NULL) ) { DWORD lastError = ::WSAGetLastError(); if ( ERROR_IO_PENDING != lastError ) { Output( _T("CSocketClient::Write() - WSASend: ") + GetLastErrorMessage( lastError ) ); if ( lastError == WSAECONNABORTED || lastError == WSAECONNRESET || lastError == WSAEDISCON) { StopConnections(); } } } if ( pBuffer->GetUsed() != pBuffer->GetWSABUF()->len ) { /* * Call to unqualified virtual function */ //OnError(_T("CSocketClient::WriteCompleted - Socket write where not all data was written")); } pBuffer->Release(); } }
CIOBuffer *CGameClient::ProcessDataStream( OnlineGameLib::Win32::CIOBuffer *pBuffer) { bool done; // DEBUG_ONLY( Output( _T("ProcessDataStream:\n") + DumpData( pBuffer->GetBuffer(), pBuffer->GetUsed(), 40 ) ) ); do { done = true; const size_t used = pBuffer->GetUsed(); if ( used >= GetMinimumMessageSize() ) { const size_t messageSize = GetMessageSize( pBuffer ); if ( messageSize == 0 ) { /* * havent got a complete message yet. * we null terminate our messages in the buffer, so we need to reserve * a byte of the buffer for this purpose... */ if ( used == ( pBuffer->GetSize() - 1 ) ) { Output( _T("Too much data!") ); /* * Write this message and then shutdown the sending side of the socket. */ Output( "found error and close this connection!" ); StopConnections(); /* * throw the rubbish away */ pBuffer->Empty(); done = true; } } else if ( used == messageSize ) { Output( _T("Got complete, distinct, message") ); /* * we have a whole, distinct, message */ pBuffer->AddData(0); // null terminate the command string; ProcessCommand( pBuffer ); pBuffer->Empty(); done = true; } else if (used > messageSize) { Output(_T("Got message plus extra data")); /* * we have a message, plus some more data * * allocate a new buffer, copy the extra data into it and try again... */ CIOBuffer *pMessage = pBuffer->SplitBuffer( messageSize ); pMessage->AddData(0); // null terminate the command string; ProcessCommand( pMessage ); pMessage->Release(); /* * loop again, we may have another complete message in there... */ done = false; } } } while ( !done ); /* * not enough data in the buffer, reissue a read into the same buffer to collect more data */ return pBuffer; }
void CTcpSocket::on_inter_close(int errid, bool bconnecting) { if (m_status != status_connect && m_status != status_common) return; XH_GUARD([&]{ closetcpsocket(m_socket); m_socket = INVALID_SOCKET; if (m_io) { if ((m_bassign & 0x01) == 0x01) m_io->Del_Event(&m_ev_read); if ((m_bassign & 0x02) == 0x02) m_io->Del_Event(&m_ev_write); m_bassign = 0; m_io->Del_TcpSocket(this); } }); m_status = status_null; switch (m_type) { case type_listener: if (m_lcb) { if (bconnecting) { m_lcb->On_Listen(GetSocketID(), errid); } m_lcb->On_Close(GetSocketID(), errid); } break; case type_accepter: if (m_acb) { if (bconnecting) { m_acb->On_Connect(GetSocketID(), errid); } while (!m_wait_send.empty()) { CIOBuffer* tmpbuf = m_wait_send.front(); XH_GUARD([&]{tmpbuf->Release(); }); m_acb->On_Send(GetSocketID(), errid, tmpbuf); m_wait_send.pop(); } while (!m_wait_recv.empty()) { CIOBuffer* tmpbuf = m_wait_recv.front(); XH_GUARD([&]{tmpbuf->Release(); }); m_acb->On_Recv(GetSocketID(), errid, tmpbuf); m_wait_recv.pop(); } m_acb->On_Close(GetSocketID(), errid); // 异常调度行为检查 while (!m_wait_send.empty()) { CIOBuffer* tmpbuf = m_wait_send.front(); XH_GUARD([&]{tmpbuf->Release(); }); m_wait_send.pop(); } while (!m_wait_recv.empty()) { CIOBuffer* tmpbuf = m_wait_recv.front(); XH_GUARD([&]{tmpbuf->Release(); }); m_wait_recv.pop(); } } break; case type_connecter: if (m_ccb) { if (bconnecting) { m_ccb->On_Connect(GetSocketID(), errid); } while (!m_wait_send.empty()) { CIOBuffer* tmpbuf = m_wait_send.front(); XH_GUARD([&]{tmpbuf->Release(); }); m_ccb->On_Send(GetSocketID(), errid, tmpbuf); m_wait_send.pop(); } while (!m_wait_recv.empty()) { CIOBuffer* tmpbuf = m_wait_recv.front(); XH_GUARD([&]{tmpbuf->Release(); }); m_ccb->On_Recv(GetSocketID(), errid, tmpbuf); m_wait_recv.pop(); } m_ccb->On_Close(GetSocketID(), errid); // 异常调度行为检查 while (!m_wait_send.empty()) { CIOBuffer* tmpbuf = m_wait_send.front(); XH_GUARD([&]{tmpbuf->Release(); }); m_wait_send.pop(); } while (!m_wait_recv.empty()) { CIOBuffer* tmpbuf = m_wait_recv.front(); XH_GUARD([&]{tmpbuf->Release(); }); m_wait_recv.pop(); } } break; default: break; } XH_LOG_INFO(logname_base, "[id:" << m_id << "] tcpsocket closed by errid : "<<errid); }
void CTcpSocket::on_inter_send(short flag) { if (m_status == status_connect) { if ((flag&EV_WRITE) == EV_WRITE) { m_status = status_common; switch (m_type) { case type_accepter: if (m_acb) { m_acb->On_Connect(GetSocketID(), tcp_ok); } break; case type_connecter: if (m_ccb) { m_ccb->On_Connect(GetSocketID(), tcp_ok); } break; default: break; } } else { XH_LOG_ERROR(logname_base, "[id:" << m_id << "] tcpsocket connect timeout"); on_inter_close(tcp_connectfail_timeout, true); return; } } else { while (!m_wait_send.empty()) { CIOBuffer* buff = m_wait_send.front(); if ( buff->AvailRead()==0 ) { XH_LOG_ERROR(logname_base, "[id:" << m_id << "] tcpsocket::send close cmd"); on_inter_close(tcp_close_byreset, false); return; } bool bneedbreak = false; int sendlen = ::send(m_socket, buff->GetCurRead(), buff->AvailRead(), 0); if ( sendlen>0 ) { buff->SeekRead(sendlen); } else if (sendlen<0) { if (isnoblockerr()) { bneedbreak = true; } else { XH_LOG_ERROR(logname_base, "[id:" << m_id << "] tcpsocket::send failed send - 1"); on_inter_close(tcp_sendfail_senderr, false); return; } } else { bneedbreak = true; } //已经写完了,则回调通知 if (buff->AvailRead()==0) { switch (m_type) { case type_accepter: if (m_acb) { m_acb->On_Send(GetSocketID(), tcp_ok, buff); } break; case type_connecter: if (m_ccb) { m_ccb->On_Send(GetSocketID(), tcp_ok, buff); } break; default: break; } m_wait_send.pop(); buff->Release(); } if (bneedbreak) break; } } if (m_wait_send.empty()) { m_io->Del_Event(&m_ev_write); } }
void CTcpSocket::on_inter_recv(short flag) { if (m_wait_recv.empty()) { m_io->Del_Event(&m_ev_read); return; } CIOBuffer* recvbuff = m_wait_recv.front(); int recvlen = ::recv(m_socket, recvbuff->GetCurWrite(), recvbuff->AvailWrite(), 0); if (recvlen == 0) { XH_LOG_INFO(logname_base, "[id:" << m_id << "] tcpsocket::recv failed, closed by peer"); on_inter_close(tcp_recvfail_closedbypeer, false); return; } else if (recvlen < 0) { if (isnoblockerr()) { ; } else { XH_LOG_WARN(logname_base, "[id:" << m_id << "] tcpsocket::recv failed, recv - 1"); on_inter_close(tcp_recvfail_recverr, false); } return; } bool bneedcb = false; recvbuff->SeekWrite(recvlen); // 如果是readsome if ( recvbuff->GetTag()==1 ) { bneedcb = true; } // 如果是读固定长度 else { // 如果读全了 if (recvbuff->AvailWrite()==0) { bneedcb = true; } } if ( !bneedcb ) { return; } switch (m_type) { case type_accepter: if (m_acb) { m_acb->On_Recv(GetSocketID(), tcp_ok, recvbuff); } break; case type_connecter: if (m_ccb) { m_ccb->On_Recv(GetSocketID(), tcp_ok, recvbuff); } break; default: break; } m_wait_recv.pop(); recvbuff->Release(); // 没有可以接收的缓存,则删除事件 if (m_wait_recv.empty()) { m_io->Del_Event(&m_ev_read); } }
void CThreadPoolWorkerThread::Process( ULONG_PTR completionKey, DWORD operation, OVERLAPPED *pOverlapped) { CSocketServer::Socket *pSocket = reinterpret_cast<CSocketServer::Socket *>(completionKey); CIOBuffer *pBuffer = static_cast<CIOBuffer *>(pOverlapped); try { switch (operation) { case CThreadPool::ConnectionEstablished: OnConnectionEstablished(pSocket, pBuffer); break; case CThreadPool::ReadCompleted: ProcessMessage(pSocket, pBuffer); break; case CThreadPool::ConnectionClosing: OnConnectionClosing(pSocket); break; case CThreadPool::ConnectionClosed: OnConnectionClosed(pSocket); break; default: // do nothing break; } } catch (const CException &e) { Output(_T("Process - Exception - ") + e.GetWhere() + _T(" - ") + e.GetMessage()); std::string strMsg = e.GetWhere() + _T(" - ") + e.GetMessage(); pSocket->Write(strMsg.c_str(), strMsg.size()); pSocket->Shutdown(); } catch (...) { Output(_T("Process - Unexpected exception")); std::string strMsg = _T("Process - Unexpected exception"); pSocket->Write(strMsg.c_str(), strMsg.size()); pSocket->Shutdown(); } pSocket->Release(); if (pBuffer) { pBuffer->Release(); } }
int CSocketClient::Run() { try { HANDLE handlesToWaitFor[2]; handlesToWaitFor[0] = m_shutdownEvent.GetEvent(); handlesToWaitFor[1] = m_successConnectionsEvent.GetEvent(); while ( !m_shutdownEvent.Wait( 0 ) ) { DWORD waitResult = ::WaitForMultipleObjects( 2, handlesToWaitFor, false, INFINITE ); if ( waitResult == WAIT_OBJECT_0 ) { /* * Time to shutdown */ break; } else if ( waitResult == WAIT_OBJECT_0 + 1 ) { /* * Allocate a buffer for required read */ CIOBuffer *pReadContext = Allocate(); while ( !m_shutdownEvent.Wait( 0 ) && m_successConnectionsEvent.Wait( 0 ) ) { if ( m_eventSelect.WaitForEnumEvent( m_connectSocket, 1000 ) ) { /* * Find some events and process it */ /* * A event to connect */ if ( m_eventSelect.IsConnect() ) { OnConnect(); } /* * A event to close */ if ( m_eventSelect.IsClose() ) { OnClose(); } /* * A event to read */ if ( m_eventSelect.IsRead() ) { OnRead( pReadContext ); } /* * A event to write */ if ( m_eventSelect.IsWrite() ) { OnWrite(); } } } // while (... pReadContext->Release(); } else { /* * Call to unqualified virtual function */ OnError( _T("CSocketClient::Run() - WaitForMultipleObjects: ") + GetLastErrorMessage( ::GetLastError() ) ); } } // while ( ... } catch( const CException &e ) { /* * Call to unqualified virtual function */ OnError( _T("CSocketClient::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() ); } catch(...) { /* * Call to unqualified virtual function */ OnError( _T("CSocketClient::Run() - Unexpected exception") ); } /* * Call to unqualified virtual function */ OnShutdownComplete(); return 0; }
int CSocketServer::WorkerThread::Run() { try { while ( true ) { /* * Continually loop to service io completion packets */ bool closeSocket = false; DWORD dwIoSize = 0; Socket *pSocket = 0; CIOBuffer *pBuffer = 0; try { m_iocp.GetStatus( (PDWORD_PTR)&pSocket, &dwIoSize, (OVERLAPPED **)&pBuffer ); } catch (const CWin32Exception &e) { if ( e.GetError() != ERROR_NETNAME_DELETED && e.GetError() != WSA_OPERATION_ABORTED ) { throw; } Output( _T("IOCP error [client connection dropped] - ") + GetLastErrorMessage( ::WSAGetLastError() ) ); closeSocket = true; } if ( !pSocket ) { /* * A completion key of 0 is posted to the iocp to request us to shut down... */ break; } /* * Call to unqualified virtual function */ OnBeginProcessing(); if ( pBuffer ) { const IO_Operation operation = static_cast<IO_Operation>( pBuffer->GetUserData() ); switch ( operation ) { case IO_Read_Request: Read( pSocket, pBuffer ); break; case IO_Read_Completed : if ( 0 != dwIoSize ) { pBuffer->Use( dwIoSize ); //DEBUG_ONLY( Output(_T("RX: ") + ToString(pBuffer) + _T("\n") + DumpData(reinterpret_cast<const BYTE*>( pBuffer->GetWSABUF()->buf), dwIoSize, 40) ) ); /* * Call to unqualified virtual function */ ReadCompleted( pSocket, pBuffer ); } else { /* * client connection dropped... */ Output( _T("ReadCompleted - 0 bytes - client connection dropped") ); closeSocket = true; } pSocket->Release(); pBuffer->Release(); break; case IO_Write_Request : Write( pSocket, pBuffer ); if ( dwIoSize != 0 ) { /* * final write, now shutdown send side of connection */ pSocket->Shutdown( SD_SEND ); } break; case IO_Write_Completed : pBuffer->Use( dwIoSize ); //DEBUG_ONLY( Output(_T("TX: ") + ToString(pBuffer) + _T("\n") + DumpData(reinterpret_cast<const BYTE*>( pBuffer->GetWSABUF()->buf), dwIoSize, 40) ) ); /* * Call to unqualified virtual function */ WriteCompleted( pSocket, pBuffer ); pSocket->Release(); pBuffer->Release(); break; case IO_Close : AbortiveClose( pSocket ); pSocket->Release(); pBuffer->Release(); break; default : /* * all to unqualified virtual function */ OnError( _T("CSocketServer::WorkerThread::Run() - Unexpected operation") ); break; } } else { /* * Call to unqualified virtual function */ OnError( _T("CSocketServer::WorkerThread::Run() - Unexpected - pBuffer is 0") ); } if ( closeSocket ) { pSocket->Close(); } /* * Call to unqualified virtual function */ OnEndProcessing(); } } catch(const CException &e) { /* * Call to unqualified virtual function */ OnError( _T("CSocketServer::WorkerThread::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() ); } catch(...) { /* * Call to unqualified virtual function */ OnError( _T("CSocketServer::WorkerThread::Run() - Unexpected exception") ); } return 0; }
int CSocketServer::Run() { try { vector<WorkerThread *> workers; workers.reserve( m_numThreads ); for ( size_t i = 0; i < m_numThreads; ++i ) { /* * Call to unqualified virtual function */ WorkerThread *pThread = CreateWorkerThread( m_iocp ); workers.push_back( pThread ); pThread->Start(); } HANDLE handlesToWaitFor[2]; handlesToWaitFor[0] = m_shutdownEvent.GetEvent(); handlesToWaitFor[1] = m_acceptConnectionsEvent.GetEvent(); while ( !m_shutdownEvent.Wait( 0 ) ) { DWORD waitResult = ::WaitForMultipleObjects( 2, handlesToWaitFor, false, INFINITE ); if ( waitResult == WAIT_OBJECT_0 ) { /* * Time to shutdown */ break; } else if ( waitResult == WAIT_OBJECT_0 + 1 ) { /* * accept connections */ while ( !m_shutdownEvent.Wait( 0 ) && m_acceptConnectionsEvent.Wait( 0 ) ) { CIOBuffer *pAddress = Allocate(); int addressSize = (int)pAddress->GetSize(); SOCKET acceptedSocket = ::WSAAccept( m_listeningSocket, reinterpret_cast<sockaddr *>(const_cast<BYTE *>( pAddress->GetBuffer() ) ), &addressSize, 0, 0); pAddress->Use( addressSize ); if ( acceptedSocket != INVALID_SOCKET ) { Socket *pSocket = AllocateSocket( acceptedSocket ); /* * Call to unqualified virtual function */ OnConnectionEstablished( pSocket, pAddress ); } else if ( m_acceptConnectionsEvent.Wait( 0 ) ) { /* * Call to unqualified virtual function */ OnError( _T("CSocketServer::Run() - WSAAccept:") + GetLastErrorMessage( ::WSAGetLastError() ) ); } pAddress->Release(); } } else { /* * Call to unqualified virtual function */ OnError( _T("CSocketServer::Run() - WaitForMultipleObjects: ") + GetLastErrorMessage( ::GetLastError() ) ); } } for ( i = 0; i < m_numThreads; ++i ) { workers[i]->InitiateShutdown(); } for ( i = 0; i < m_numThreads; ++i ) { workers[i]->WaitForShutdownToComplete(); delete workers[i]; workers[i] = 0; } } catch( const CException &e ) { /* * Call to unqualified virtual function */ OnError( _T("CSocketServer::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() ); } catch(...) { /* * Call to unqualified virtual function */ OnError( _T("CSocketServer::Run() - Unexpected exception") ); } /* * Call to unqualified virtual function */ OnShutdownComplete(); return 0; }