基于TCP/IP socket文件传输 外网传输数据丢失

destinyC 2012-11-20 11:39:05
各位好:
第一次写网络传输相关程序,目前在项目中遇到一个问题。在数据传输过程中,内网测试没有问题,但是在连接外网服务器时,Client接收到的数据和Server发送的数据会出现不同的情况(具体是在数据的结尾部分会有约596字节为空)。
后来我加入了对接收数据的MD5码校验,不同则再次请求上一次数据。但是这样很影响速率。
以下是部分代码:

//客户端数据解析(前4个字节是协议含解析MD5校验位,接着4字节是数据大小不包含MD5长度)
BOOL CDataSolver::DataAnalysis( PCHAR pDataAddr ,EPackageData& pPack ,BOOL& bNeedEncode )
{
if(pDataAddr == NULL)
return FALSE;
DWORD dwProtocol = 0;
memcpy(&dwProtocol ,pDataAddr ,sizeof(DWORD));
pPack.dwDataSize = 0;
pPack.dwProtocol = dwProtocol & (~PROT_ENCODE_MD5);
bNeedEncode = (dwProtocol & PROT_ENCODE_MD5) == PROT_ENCODE_MD5;
DWORD dwDataSize = 0;
switch (pPack.dwProtocol)
{
case 需要接收数据:
{
memcpy(&dwDataSize ,pDataAddr + sizeof(DWORD) ,sizeof(DWORD));
pPack.dwDataSize = dwDataSize;
dwDataSize = dwDataSize > MD_DATA_NORMAL_LENGTH ? 0 : dwDataSize;

if(bNeedEncode) //如果有MD5码,则拷贝MD5数据
{
pPack.pCodeAddr = new CHAR[MD_DATA_MD5_LENGTH + 1];
memcpy(pPack.pCodeAddr ,pDataAddr + MD_DATAHEAD_LENGTH ,MD_DATA_MD5_LENGTH);
pPack.pCodeAddr[MD_DATA_MD5_LENGTH] = '\0';
}

if(dwDataSize > 0)
{
pPack.pDataAddr = new CHAR[dwDataSize + 1];
DWORD dwLast = MD_DATAHEAD_LENGTH;
dwLast += bNeedEncode ? MD_DATA_MD5_LENGTH : 0;
memcpy(pPack.pDataAddr ,pDataAddr + dwLast,dwDataSize);
pPack.pDataAddr[dwDataSize] = '\0';
}
}
break;
}

return TRUE;
}




//服务端数据打包及传输
VOID CFunctionRuntime::SendData( EPackageData pPack ,SOCKET pSock)
{
DWORD dwDataSize = 0;
dwDataSize += sizeof(DWORD); //协议
dwDataSize += sizeof(DWORD); //数据长度
if(pPack.dwDataSize > 0)
{
dwDataSize += pPack.dwDataSize; //数据流长度
}

if( (pPack.dwProtocol & PROT_ENCODE_MD5) == PROT_ENCODE_MD5) //或运算,计算是否有MD5附加项
{
dwDataSize += MD_DATA_MD5_LENGTH; //MD5码长度
}

PCHAR pDataAddr = new CHAR[dwDataSize + 1];
memset(pDataAddr ,0 ,dwDataSize + 1);
memcpy(pDataAddr ,&pPack.dwProtocol ,sizeof(DWORD));
memcpy(&pDataAddr[4] ,&pPack.dwDataSize ,sizeof(DWORD)); //protocol + datasize 固定8个字节

if( (pPack.dwProtocol & PROT_ENCODE_MD5) == PROT_ENCODE_MD5
&& pPack.pCodeAddr)
{
memcpy(&pDataAddr[MD_DATAHEAD_LENGTH] ,pPack.pCodeAddr ,MD_DATA_MD5_LENGTH);
}

if(pPack,dwDataSize > 0 && pPack.pDataAddr)
{
DWORD dwLast = MD_DATAHEAD_LENGTH;
dwLast += ((pPack.dwProtocol & PROT_ENCODE_MD5) == PROT_ENCODE_MD5) ? MD_DATA_MD5_LENGTH : 0;
memcpy(&pDataAddr[dwLast] ,pPack.pDataAddr ,pPack.dwDataSize);
}

TcpCommAdapter::GetInstance()->SendData(pDataAddr ,dwDataSize ,pSock);
delete[] pDataAddr;
}

DWORD TcpCommAdapter::SendData( PCHAR pDataAddr ,DWORD dwDataSize ,SOCKET pSock )
{
DWORD dwSendSize = 0;
CGlobalInstance::GetInstance()->GlobalLock();
DWORD dwRemainSize = dwDataSize;
if(pDataAddr && IsServerAlive())
{
//while (dwRemainSize > 0)
//{
// dwSendSize = send(pSock ,pDataAddr ,dwRemainSize ,0);
// if(dwSendSize == 0 || dwSendSize == SOCKET_ERROR)
// {
// break;
// }
// dwRemainSize -= dwSendSize;
// pDataAddr += dwSendSize;
//}
//INT nSize = 0;
//setsockopt(pSock ,SOL_SOCKET ,SO_SNDBUF ,(CHAR*)&nSize ,sizeof(nSize));
dwSendSize = send(pSock ,pDataAddr ,dwRemainSize ,0);
}
CGlobalInstance::GetInstance()->GlobalUnlock();
return dwDataSize ;//== dwDataSize - dwRemainSize ? SD_SOCKET_SEND_SUCCESS : SD_SOCKET_SEND_ERR;
}
...全文
373 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
cook_fish 2014-08-22
  • 打赏
  • 举报
回复
楼主,请问你tcp传输数据在外网能够正常收发吗?我这边发一个数据出去,server端只收了一小部分,就不去收了,不知道怎么回事,求指导。
destinyC 2012-11-20
  • 打赏
  • 举报
回复
再顶一下。。
destinyC 2012-11-20
  • 打赏
  • 举报
回复
Client数据分析代码也在上面,应该是没问题,我也是按照Server打包的格式逆解析出来的。因为在内网测试的时候没有出现这个问题,所以很是奇怪。
winginsky 2012-11-20
  • 打赏
  • 举报
回复
应该不会出现这种情况,你Client组包时是否有问题?
destinyC 2012-11-20
  • 打赏
  • 举报
回复
自己顶一下。
xumaojun 2012-11-20
  • 打赏
  • 举报
回复
TCP传输本来就是基于字节流的,怎么又沾包呢?发送了多少字节就接收多少字节呀
destinyC 2012-11-20
  • 打赏
  • 举报
回复
TO 5楼: 我的协议格式是:DWORD协议(含MD5校验位)+DWORD有效数据长度+32字节MD5校验码+2046字节最大有效数据。所以收发正确的话,应该不会有数据长度错误的问题。不过谢谢你的提醒。
destinyC 2012-11-20
  • 打赏
  • 举报
回复
我好像找到问题了: 我发送的包大小是最大不超过:DWORD+DWORD+32+2046 字节。貌似出现粘包了。我一直以为长度低于4K多字节传输时不会被拆包。然后我把传输包大小改成最大不超过:DWORD+DWORD+32+1024之后低于电信MTU的1.4K多之后传输就正常了。 不过很明显传输速率降得很厉害,看来这块需要重写一下处理粘包了。唉,学艺不精。谢谢3L关心了。
  • 打赏
  • 举报
回复
正常情况下是不会这样的。 可以在你的数据前加一个数据包头,先接收固定长度的包头,从包头中得到数据长度,再接收数据。

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧