void CSocketServer::Write( Socket *pSocket, const char *pData, size_t dataLength, bool thenShutdown) { if ( !pSocket || !pData || dataLength <= 0 ) { return; } /* * Post a write request to the iocp so that the actual socket write gets performed by * one of our IO threads... */ CIOBuffer *pBuffer = Allocate(); /* * Call to unqualified virtual function */ #ifdef NETWORK_DEBUG //{ PreWrite( pSocket, pBuffer, pData, dataLength + PACK_HEADER_LEN + sizeof(BYTE) ); //} #else //{ PreWrite( pSocket, pBuffer, pData, dataLength ); //} #endif // NETWORK_DEBUG pBuffer->AddData( pData, dataLength ); #ifdef NETWORK_DEBUG //{ const BYTE *pPackData = pBuffer->GetBuffer(); PACK_HEADER ph = {0}; memcpy( (BYTE *)&ph, pPackData, PACK_HEADER_LEN ); pBuffer->AddData( (BYTE *)&ph, PACK_HEADER_LEN ); pBuffer->AddData( 0xAA ); //} #endif // NETWORK_DEBUG pBuffer->SetUserData( IO_Write_Request ); pSocket->AddRef(); m_iocp.PostStatus( (ULONG_PTR)pSocket, thenShutdown, pBuffer ); }
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 *CIOBuffer::SplitBuffer( size_t bytesToRemove ) { CIOBuffer *pNewBuffer = m_allocator.Allocate(); pNewBuffer->AddData( m_buffer_ptr, bytesToRemove ); m_used -= bytesToRemove; memmove( m_buffer_ptr, m_buffer_ptr + bytesToRemove, m_used ); return pNewBuffer; }
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; }