⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iocppacket.cpp

📁 iocp vc例子,自己是学DELPHI
💻 CPP
字号:
// IocpPacket.cpp: implementation of the CIocpPacket class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "IocpPacket.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CIocpPacket::CIocpPacket()
{
	m_ulKey = 0;
	m_wType = PACKETTYPE_NONE;
	ResetPacket();
}

CIocpPacket::~CIocpPacket()
{
	ClosePacketFile();
	DeleteAllFile();
}

void CIocpPacket::ResetPacket()
{
	m_nBufLen = m_nTranLen = 0;
	m_bDeleteAfterSend = FALSE;
	m_bHeaderSerialize = FALSE;
	m_nHeaderLen = m_nFileIndex = m_nFileCurrentLength = 0;
	m_strDefaultPath.Empty();
	m_nDoneLength = m_nLastInfoLength = m_nOneInfoLength = 0;
	m_bSyncSend = FALSE;

	ClosePacketFile();
	
	m_pkHeader.ResetHeader();
	m_memHeader.SetLength(0);
	m_memPacket.SetLength(0);
}

int CIocpPacket::ReadData(BYTE* szData, int nDataLen, int nReadedLen)
{
	int nRet=0;
	//要考虑缓冲区中的标识所占的字节数
	ASSERT(szData!=NULL && nDataLen>=0);

	BYTE* p=szData;
	memcpy(p, &m_ulKey, KEYLEN);	//先拷贝标识
	nRet += KEYLEN;
	
	//偏移数据
	p += KEYLEN;
	nDataLen -= KEYLEN;
	if (nDataLen<=0) return nRet;

	//根据nReadedLen跳过已读数据
	int nRestLen=MINPACKETLEN-nReadedLen;
	if (nRestLen>0)	//写包头长度
	{
		if (nDataLen<=nRestLen)
		{
			memcpy(p, &m_nHeaderLen+nReadedLen, nDataLen);
			nRet += nDataLen;
		}
		else
		{
			memcpy(p, &m_nHeaderLen+nReadedLen, nRestLen);
			nRet += nRestLen;
		}
		//偏移数据
		p += nRestLen;
		nDataLen -= nRestLen;
		if (nDataLen<=0) return nRet;
		nReadedLen = 0;
	}
	else
	{			
		nReadedLen -= MINPACKETLEN;
	}

	//写包头数据
	nRestLen = m_nHeaderLen-nReadedLen;
	if (nRestLen>0)
	{
		if (nDataLen<=nRestLen)
		{
			memcpy(p, m_memHeader.GetDataBuf()+nReadedLen, nDataLen);
			nRet += nDataLen;
		}
		else
		{
			memcpy(p, m_memHeader.GetDataBuf()+nReadedLen, nRestLen);
			nRet += nRestLen;
		}
		//偏移数据
		p += nRestLen;
		nDataLen -= nRestLen;
		if (nDataLen<=0) return nRet;
		nReadedLen = 0;
	}
	else
	{		
		nReadedLen -= m_nHeaderLen;
	}

	//写包数据
	nRestLen = m_pkHeader.m_nDataLen-nReadedLen;
	if (nRestLen>0)
	{
		if (nDataLen<=nRestLen)
		{
			memcpy(p, m_memPacket.GetDataBuf()+nReadedLen, nDataLen);
			nRet += nDataLen;
		}
		else
		{
			memcpy(p, m_memPacket.GetDataBuf()+nReadedLen, nRestLen);
			nRet += nRestLen;
		}
		//偏移数据
		p += nRestLen;
		nDataLen -= nRestLen;
		if (nDataLen<=0) return nRet;
		nReadedLen = 0;
	}
	else
	{		
		nReadedLen -= m_pkHeader.m_nDataLen;
	}

	//写文件数据
	ZNET_TRY
	{
		//获得文件数据
		while (nDataLen>0)	//若仍有数据未处理
		{	
			if (m_nFileIndex<0 || m_nFileIndex>=m_pkHeader.m_aFullName.GetSize())
				break;	//文件序号无效跳出
			
			CString strFullName=m_pkHeader.m_aFullName[m_nFileIndex];
			int nFileLength=m_pkHeader.m_aFileLength[m_nFileIndex];
			nRestLen = nFileLength-nReadedLen;
			if (nRestLen>0)
			{
				if (m_nFileCurrentLength==0)	//打开文件
				{
					ClosePacketFile();
					m_fReadWrite.Open(strFullName, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeRead|CFile::typeBinary|CFile::shareDenyWrite);
				}

				if (nDataLen<=nRestLen)
				{
					m_fReadWrite.Read(p, nDataLen);
					m_nFileCurrentLength += nDataLen;
					nRet += nDataLen;
				}
				else
				{
					m_fReadWrite.Read(p, nRestLen);
					m_nFileCurrentLength += nRestLen;
					nRet += nRestLen;
				}

				//偏移数据
				p += nRestLen;
				nDataLen -= nRestLen;
				nReadedLen = 0;
				if (m_nFileCurrentLength>=nFileLength)	//关闭文件
				{
					m_nFileCurrentLength = 0;
					m_nFileIndex ++;
					ClosePacketFile();
				}
			}
			else	//当前文件不需要数据则递增文件序号
			{
				nReadedLen -= nFileLength;
				//清除数据继续处理下一个文件
				m_nFileCurrentLength = 0;
				m_nFileIndex ++;
				ClosePacketFile();
			}
		}
	}
	ZNET_CATCH
	ZNET_CATCH_ALL(ERROR_IOCPPACKET_PROCESSING_FILE);

	//若不足nDataLen则补NULL
	if (nDataLen>0)
	{
		memset(p, 0, nDataLen);
		nRet += nDataLen;
	}

	return nRet;
}

int CIocpPacket::WriteData(const BYTE* szData, int nDataLen)
{
	ASSERT(szData!=NULL && nDataLen>=0);

	m_nBufLen += nDataLen;
	m_nDoneLength += nDataLen;	//记录已接收数据长度
	int nErr=ERROR_NONE;
	const BYTE* p=szData;
	if (!m_bHeaderSerialize)	//若包头未序列化
	{
		if (m_nHeaderLen<=0)	//若包头长度未知
		{
			if (nDataLen<MINPACKETLEN)
			{
				nErr = ERROR_IOCPPACKET_DATA_NOT_ENOUGH;
				Logging2(nErr, DOMAIN_NAME);
				return nErr;
			}
			//获得包头长度
			memcpy(&m_nHeaderLen, p, MINPACKETLEN);	
			//偏移数据
			p += MINPACKETLEN;
			nDataLen -= MINPACKETLEN;
			if (nDataLen<=0) return nErr;
		}		

		//写包头数据
		int nMemLen=m_memHeader.GetDataBufLen();
		int nNeedLen=m_nHeaderLen-nMemLen;
		if (nNeedLen>0)
		{		
			if (nDataLen>=nNeedLen)
			{
				m_memHeader.Write(p, nNeedLen);
				m_memHeader.SeekToBegin();
				m_bHeaderSerialize = TRUE;

				ZNET_TRY
				{				
					CArchive ar(&m_memHeader, CArchive::load|CArchive::bNoFlushOnDelete);
					m_pkHeader.Serialize(ar);
					ar.Close();
				}
				ZNET_CATCH
				ZNET_CATCH_ALL_WITH_RETURN(ERROR_IOCPPACKET_HEADER_SERIALIZE);

				//修改临时文件名
				int nFileSize=0;
				for (int i=0; i<m_pkHeader.m_aFileName.GetSize(); i++)
				{
					m_pkHeader.m_aFullName[i] = CPublicFunc::GetFullTempName(m_strDefaultPath);
					nFileSize += m_pkHeader.m_aFileLength[i];
				}

				//计算实际传输的长度
				int nBufLen = MINPACKETLEN+m_nHeaderLen+m_pkHeader.m_nDataLen+nFileSize;
				m_nTranLen = ComputeTranSize(nBufLen);
				m_nOneInfoLength = m_nTranLen/100;
			}
			else
			{
				m_memHeader.Write(p, nDataLen);
			}
			//偏移数据
			p += nNeedLen;
			nDataLen -= nNeedLen;
			if (nDataLen<=0) return nErr;
		}		
	}

	if (m_pkHeader.m_nDataLen>0)	//获得数据
	{
		int nPacketDataLen=m_memPacket.GetDataBufLen();
		int nNeedLen=m_pkHeader.m_nDataLen-nPacketDataLen;
		if (nNeedLen>0)
		{
			if (nDataLen>=nNeedLen)
			{
				m_memPacket.Write(p, nNeedLen);
			}
			else
			{
				m_memPacket.Write(p, nDataLen);
			}
			//偏移数据
			p += nNeedLen;
			nDataLen -= nNeedLen;
			if (nDataLen<=0) return nErr;
		}		
	}

	ZNET_TRY
	{
		//获得文件数据
		while (nDataLen>0)	//若仍有数据未处理
		{	
			if (m_nFileIndex<0 || m_nFileIndex>=m_pkHeader.m_aFullName.GetSize())
				break;	//文件序号无效跳出
			
			CString strFullName=m_pkHeader.m_aFullName[m_nFileIndex];
			int nFileLength=m_pkHeader.m_aFileLength[m_nFileIndex];
			int nNeedLen = nFileLength-m_nFileCurrentLength;
			if (nNeedLen>0)	//若当前文件需要数据
			{
				if (m_nFileCurrentLength==0)	//打开文件
				{				
					ClosePacketFile();					
					m_fReadWrite.Open(strFullName, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite|CFile::typeBinary|CFile::shareDenyWrite);
				}

				if (nDataLen>=nNeedLen)
				{
					m_fReadWrite.Write(p, nNeedLen);
					m_nFileCurrentLength += nNeedLen;
				}
				else
				{
					m_fReadWrite.Write(p, nDataLen);
					m_nFileCurrentLength += nDataLen;
				}

				//偏移数据
				p += nNeedLen;
				nDataLen -= nNeedLen;
				if (m_nFileCurrentLength>=nFileLength)	//关闭文件
				{
					m_nFileCurrentLength = 0;
					m_nFileIndex ++;
					ClosePacketFile();
				}
			}
			else	//当前文件不需要数据则递增文件序号
			{
				//清除数据继续处理下一个文件
				m_nFileCurrentLength = 0;
				m_nFileIndex ++;
				ClosePacketFile();	
			}
		}
	}
	ZNET_CATCH
	ZNET_CATCH_ALL(ERROR_IOCPPACKET_PROCESSING_FILE);

	return nErr;
}

int CIocpPacket::Clone(CIocpPacket* pPacket)
{
	int nErr=ERROR_NONE;
	if (pPacket==NULL)
	{
		nErr = ERROR_FUNC_PARAM_INVALID;
		return nErr;
	}
	pPacket->m_bDeleteAfterSend = pPacket->m_bDeleteAfterSend;
	//复制包头
	pPacket->m_pkHeader = m_pkHeader;
	//复制包数据
	int nNeedLen=m_memPacket.GetDataBufLen();
	pPacket->m_memPacket.SeekToBegin();
	pPacket->m_memPacket.Write(m_memPacket.GetDataBuf(), nNeedLen);

	return nErr;
}

BOOL CIocpPacket::IsReady()
{	
	BOOL bRet=(m_nTranLen>0 && m_nTranLen==m_nBufLen);	
	return bRet;
}

BOOL CIocpPacket::IsOver(int nSize)
{
	BOOL bRet=FALSE;
	if (m_nTranLen>0)
		bRet = (m_nTranLen==nSize);
	m_nDoneLength = nSize;	//记录已发送数据长度
	return bRet;
}

int CIocpPacket::ComputeTranSize(int nBufLen)
{
	int nPackateLen=(MAXBUFLEN-KEYLEN);	
	int nRemainder=nBufLen%nPackateLen;
	int nTime=((nBufLen/nPackateLen)+((nRemainder!=0)?1:0));
	return nPackateLen*nTime;
}

void CIocpPacket::InitSendData()
{
	m_pkHeader.m_nDataLen = m_memPacket.GetDataBufLen();

	if (!m_bHeaderSerialize)
	{	
		//序列化包头数据
		CArchive ar(&m_memHeader, CArchive::store);
		m_pkHeader.Serialize(ar);
		ar.Close();
		m_nHeaderLen = m_memHeader.GetDataBufLen();
		m_bHeaderSerialize = TRUE;
	}

	//计算实际传输的长度
	int nFileSize=0;
	for (int i=0; i<m_pkHeader.m_aFileLength.GetSize(); i++)
	{		
		nFileSize += m_pkHeader.m_aFileLength[i];
	}	
	m_nBufLen = MINPACKETLEN+m_nHeaderLen+m_pkHeader.m_nDataLen+nFileSize;
	m_nTranLen = ComputeTranSize(m_nBufLen);
	m_nOneInfoLength = m_nTranLen/100;
}

BOOL CIocpPacket::NeedInfoProgress(int& nTranLen, int& nDoneLen)
{
	BOOL bRet=FALSE;
	if (m_nOneInfoLength>0)
	{
		int nPercent=(m_nDoneLength-m_nLastInfoLength)/m_nOneInfoLength;		
		nDoneLen = m_nDoneLength;
		nTranLen = m_nTranLen;
		if (nPercent>PERCENT_INFO_TRANSFER_PROGRESS && 
			GetPacketFileCount()>0)	//传输文件且进度大于指定值才通知
		{
			m_nLastInfoLength = m_nDoneLength;
			bRet = TRUE;
		}
	}
	return bRet;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -