欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[讨论]Gh0st3.6 IOCP发送BUG

[讨论]Gh0st3.6 IOCP发送BUG

测试发现有时客户端会发送重复数据包,感觉作者的IOCP发送处理逻辑不是太清晰,简单修改了下,初步测试没发现异常
话说我很想不通使用了TCP通信的Gh0st里面居然还有处理重发的代码,真是蛋疼啊,懒得删了,万一有个大坑呢?
另外里面频繁的new delete看得我也很不爽啊,不过我忍住了,能不动就不动
1、CIOCPServer::Send

void[B] CIOCPServer::Send[/B](ClientContext* pContext, LPBYTE lpData, UINT nSize)
{
	if (pContext == NULL)
		return;
	try
	{
                CLock cs(pContext->m_SndLock, "Send");
		if (nSize > 0)
		{
			// Compress data
			unsigned long	destLen = (double)nSize * 1.001  + 12;
			LPBYTE			pDest = new BYTE[destLen];
			int	nRet = compress(pDest, &destLen, lpData, nSize);
			if (nRet != Z_OK)
			{
				delete [] pDest;
				return;
			}
			//////////////////////////////////////////////////////////////////////////
			LONG nBufLen = destLen + HDR_SIZE;
			// 5 bytes packet flag
			pContext->m_WriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));
			// 4 byte header [Size of Entire Packet]
			pContext->m_WriteBuffer.Write((PBYTE) &nBufLen, sizeof(nBufLen));
			// 4 byte header [Size of UnCompress Entire Packet]
			pContext->m_WriteBuffer.Write((PBYTE) &nSize, sizeof(nSize));
			// Write Data
			pContext->m_WriteBuffer.Write(pDest, destLen);
			delete [] pDest;
			// 如果当前缓冲区无数据堆积,执行PostSend
			[B]if (pContext->m_WriteBuffer.GetBufferLen() == nBufLen)
				PostSend(pContext);[/B]
			// 发送完后,再备份数据, 因为有可能是m_ResendWriteBuffer本身在发送,所以不直接写入
			LPBYTE lpResendWriteBuffer = new BYTE[nSize];
			CopyMemory(lpResendWriteBuffer, lpData, nSize);
			pContext->m_ResendWriteBuffer.ClearBuffer();
			pContext->m_ResendWriteBuffer.Write(lpResendWriteBuffer, nSize);	// 备份发送的数据
			delete [] lpResendWriteBuffer;
		}
		else // 要求重发
		{
			pContext->m_WriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));
			pContext->m_ResendWriteBuffer.ClearBuffer();
			pContext->m_ResendWriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag));	// 备份发送的数据	
		}
 		//OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IOWrite);
 		//PostQueuedCompletionStatus(m_hCompletionPort, 0, (DWORD) pContext, &pOverlap->m_ol);
		pContext->m_nMsgOut++;
	}catch(...){}
}

2、添加函数CIOCPServer::PostSend
void [B]CIOCPServer::PostSend[/B](ClientContext* pContext)
{
	OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IOWrite);
	WSABUF sndBuf;
	ULONG ulFlags = MSG_PARTIAL;
	m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_TRANSMIT);
	sndBuf.buf = (char*) pContext->m_WriteBuffer.GetBuffer();
	sndBuf.len = pContext->m_WriteBuffer.GetBufferLen();
	int nRetVal = WSASend(pContext->m_Socket, 
		&sndBuf,
		1,
		&sndBuf.len, 
		ulFlags,
		&pOverlap->m_ol, 
		NULL);
	if (nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
		RemoveStaleClient( pContext, FALSE );
}

3、CIOCPServer::OnClientWriting
bool [B]CIOCPServer::OnClientWriting[/B](ClientContext* pContext, DWORD dwIoSize)
{
	try
	{
		//////////////////////////////////////////////////////////////////////////
		static DWORD nLastTick = GetTickCount();
		static DWORD nBytes = 0;
		nBytes += dwIoSize;
		if (GetTickCount() - nLastTick >= 1000)
		{
			nLastTick = GetTickCount();
			InterlockedExchange((LPLONG)&(m_nSendKbps), nBytes);
			nBytes = 0;
		}
		//////////////////////////////////////////////////////////////////////////
                TRACE("IOCP Send DONE %d bytes Remain:%d bytes\n", 
			dwIoSize, 
			pContext->m_WriteBuffer.GetBufferLen());
		// Finished writing - tidy up
                if (dwIoSize > 0){
		        pContext->m_WriteBuffer.Delete(dwIoSize);
			[B]if (pContext->m_WriteBuffer.GetBufferLen() > 0)
				PostSend(pContext);[/B]
			else
				pContext->m_WriteBuffer.ClearBuffer();
                }
	}catch(...){}
	return false;			// issue new read after this one
}

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功