📄 iocppacket.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 + -