关于用SOCKET编写下载程序时出现数据丢失的问题

「已注销」 2010-12-05 03:35:16
大家好,我是一个新手,希望大家帮帮我。
我用socket编写一个下载程序,客户端和服务端都在本地测试时,对于小文件不会出现错误,但对于大文件就会出现错误,也不是每次都出错,是随机性的。但是当把服务端放在远程电脑运行时,再下载文件,不管多大都会出现错误。

先贴一部分代码给大家查看下:
这是客户端部分代码

long Filesize=Downfile.fileLen; //接收到的文件长度
int iSize=0;
char recvBuf[256];
ofstream outfile(GetThreadData.SavePath,ios::binary);
while(Filesize>0)
{
memset(recvBuf,'\0',sizeof(recvBuf));
recv(GetThreadData.m_sock,recvBuf,sizeof(recvBuf),0);
iSize=sizeof(recvBuf);
if(Filesize>=iSize)
{
outfile.write(recvBuf,iSize);
Filesize-=iSize;
}
else
{
outfile.write(recvBuf,Filesize);
Filesize=0;
}
}
outfile.close();
closesocket(GetThreadData.m_sock);


这是服务端部分代码

MESSAGEDATA Sendinfo;
ifstream file(FilePath,ios::binary); //以二进制读入的方式打开文件,FilePath是接收到的文件下载路径
if(!file)
{
memset(&Sendinfo,'\0',sizeof(Sendinfo));
Sendinfo.ID=REFUSE_REQUEST;
send(sock,(const char*)&Sendinfo,sizeof(Sendinfo),0); //发送文件上传失败信息
return;
}
else
{
char sendBuf[256]=""; //数据缓存区
WIN32_FIND_DATA Fileinfo;
FindClose(FindFirstFile(FilePath,&Fileinfo));
memset(&Sendinfo,'\0',sizeof(Sendinfo));

Sendinfo.ID=RECEIVE_REQUEST;
Sendinfo.fileLen=Fileinfo.nFileSizeHigh*MAXDWORD+Fileinfo.nFileSizeLow;
send(sock,(const char*)&Sendinfo,sizeof(Sendinfo),0); //发送文件确认信息
Sleep(500);
if(file)
{
//判断结尾
while(!file.eof())
{
file.read(sendBuf,sizeof(sendBuf)); //读文件
send(sock,sendBuf,sizeof(sendBuf),0);
memset(sendBuf,'\0',sizeof(sendBuf));
}
}
file.close();
}
...全文
62 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
码农心语 2010-12-05
  • 打赏
  • 举报
回复
应该不是对包不丢包的问题,这个tcp帮我们解决了可靠性的问题。
我们要知道,recv函数不保证你想收n个字节就等到收到了才返回了。

如果有1个字节收到,都可能直接返回了。你要做一个循环,自己来计数,判断是否已经收到了你想要的字节数。

send函数也是类似的。
C你 2010-12-05
  • 打赏
  • 举报
回复
你这样发送接收文件是不行的,你这边一直发,那边一直接收,就算tcp也是会丢包的啊,你发送一个包过去之后,要验证下,控制一下下载的速度,然后再发下一个包,最后下载完毕之后最好再用MD5验证一下,文件时候下载正确。
open_studio 2010-12-05
  • 打赏
  • 举报
回复
请检查一下是否是没有检查send的返回值,如果send失败,根据错误码处理重传,代码如下:
file.read(sendBuf,sizeof(sendBuf)); //读文件
send(sock,sendBuf,sizeof(sendBuf),0);
if (发送POOL满错误)
{
//休息一会重传
}
else if(网络错误)
{
//重新连接,会话是重传或续传
}
.....

此外,关于文件传输,控制是很复杂的,上述的代码太简单了,无法商业化,挂死了都不知道是什么原因
kingstarer 2010-12-05
  • 打赏
  • 举报
回复
我一般习惯写一个Send和Recv函数

作用是重复调用send和recv,直到完全发送或接收所有字节,或者是超出预期调用次数时才返回。
kingstarer 2010-12-05
  • 打赏
  • 举报
回复
你的send和recv都没有判断返回值

网络好的情况下,send和recv的字节数跟你要发送和接收的字节数是相同的

但是网络不好就不一定了
「已注销」 2010-12-05
  • 打赏
  • 举报
回复
额,怎么没有人呢?
哎,我自己先顶一下。

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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