用Socket 文件传输,传大文件时,接收的文件损坏,这是怎么回事呢?

icemoon1987 2008-07-21 02:56:27
我是一名刚开始学MFC的大学生,试着编了一个用socket传输文件的程序。
思路是把文件一次性读入缓冲区,然后用TCP发送,接收方一次性把文件接收入缓冲区,然后再写成文件。
我试着用这个程序传送了一些小的文本文件,一切正常,也传了一些MP3,正常。
但是在传送一些100多M的RMVB视频文件时,接收到的文件却无法打开
请问各位高手这是怎么回事呢?谢谢了。

该开始学,分不多,请见谅。

程序代码如下:

服务器端:

void CFileTransDlg::OnSend()
{
// TODO: Add your control notification handler code here

CFileDialog fd(true);
CString filename;
char fn[40];

SOCKET listenSocket;
SOCKET socketSend;
unsigned int listen_port;


CFile file;
int FileLength;
char *data;

struct sockaddr_in localaddr;
struct sockaddr_in clientaddr;

listen_port=5050;

int AddrSize;

AddrSize = sizeof(clientaddr);

if(IDOK == fd.DoModal())
{

filename = fd.GetFileName();
if(!file.Open(filename.GetBuffer(0),CFile::modeRead|CFile::typeBinary))
{
AfxMessageBox("打开文件错误,取消发送!");
return;
}
strcpy(fn,filename.GetBuffer(0));

}
else return;

listenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
socketSend = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(listen_port);


if (bind(listenSocket, (struct sockaddr *)&localaddr,
sizeof(localaddr)) == SOCKET_ERROR)
{
AfxMessageBox("绑定socket失败 : %d\n", WSAGetLastError());
return ;
}


listen(listenSocket,20);


socketSend = accept(listenSocket,(struct sockaddr *)&clientaddr,&AddrSize);

FileLength = file.GetLength();


char acBuf[50] = { 0 };
sprintf(acBuf, "%d", FileLength);

send(socketSend,acBuf,50,0);
send(socketSend,fn,40,0);

data = new char[FileLength];

file.ReadHuge(data,FileLength);

send(socketSend,data,FileLength,0);



file.Close();
delete data;
closesocket(socketSend);

WSACleanup();

}

客户端:

void CFileTransClientDlg::OnReceive()
{
// TODO: Add your control notification handler code here

SOCKET socketReceive;
CFile file;
long FileLength = 0;
char tem[50];
char *data;
char fn[40];
struct sockaddr_in server;
unsigned int server_port=5050;

server.sin_family = AF_INET;
server.sin_port = htons(server_port);
server.sin_addr.s_addr = inet_addr("222.25.136.114");


InitWinsock();

socketReceive = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

connect(socketReceive,(struct sockaddr *)&server,sizeof(server));

recv(socketReceive,tem,50,0);

FileLength = chartoint(tem);

recv(socketReceive,fn,40,0);

data = new char[FileLength];

recv(socketReceive,data,FileLength,0);

file.Open(fn,CFile::modeCreate |CFile::modeWrite|CFile::typeBinary);

file.WriteHuge(data,FileLength);

file.Close();

delete data;

closesocket(socketReceive);

AfxMessageBox("接收文件成功!");

WSACleanup();

}
...全文
868 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
ang3659467 2010-10-09
  • 打赏
  • 举报
回复
继续学习!!!!
liaoning33 2010-08-09
  • 打赏
  • 举报
回复
icemoon1987 2008-07-21
  • 打赏
  • 举报
回复
哦,我明白了,我想接收那边我也能写出来了,太谢谢你了!
剩下的我自己尝试吧。

嘿嘿,要学的东西真是太多了,太感谢了!!
thirddata 2008-07-21
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 icemoon1987 的回复:]
哦,太谢谢了。我大概有思路了。
但是现在还不明白一个地方。
Send函数有三个参数,我要怎样确定它从那个字节开始发呢?
还是我把没发完的数据再放入另一个缓冲区,然后调用Send发送呢?
另外recv函数,要怎么样才能控制它接收了数据后加入刚才的缓冲区后面呢?
还是我要重新开辟一片缓冲区,然后接受完后,再连接起来?
[/Quote]
int nLeft = nLength;
while(nLeft > 0){
//can write
int nSent = ::send(s,
pszBuffer + (nLength - nLeft),nLeft,0);
if(SOCKET_ERROR == nSent){
//error
break;
}
else{
nLeft -= nSent;
}
}
icemoon1987 2008-07-21
  • 打赏
  • 举报
回复
哦,太谢谢了。我大概有思路了。
但是现在还不明白一个地方。
Send函数有三个参数,我要怎样确定它从那个字节开始发呢?
还是我把没发完的数据再放入另一个缓冲区,然后调用Send发送呢?
另外recv函数,要怎么样才能控制它接收了数据后加入刚才的缓冲区后面呢?
还是我要重新开辟一片缓冲区,然后接受完后,再连接起来?
icemoon1987 2008-07-21
  • 打赏
  • 举报
回复
恩,是不是一个Send函数一次发送的数据有个最大限制啊?

如果要再次发送剩余数据的话,我怎么知道刚才发送到哪儿了呢?

不好意思啊,我是个初学者,还什么多不太懂。

能不能麻烦你说的详细一点?
谢谢了!
thirddata 2008-07-21
  • 打赏
  • 举报
回复
比如你发送char szBuffer[1024],
调用一次send,send返回512,说明这次send只发送成功了512字节
应该再次调用send,发送下面的512字节,
去看msdn
thirddata 2008-07-21
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 icemoon1987 的回复:]
谢谢啊,我刚开始学,对于Socket和TCP的理解还很浅。

我用一个Send语句传送文件,是系统自动把这个文件分成很多份在打包发送的吗??

如果是的话,是不是接收后系统自动在把这些包组合起来?
我应该怎样才能加上验证呢?

不麻烦你帮忙写代码,只要讲一下思路就可以了。另外能告诉我该去看书上的那一部分相关知识吗?
我想把这个问题弄清楚。

再次谢谢了!
[/Quote]
系统不会帮你分包的,你应该检查send的返回值,看看是否所有数据都发送了,如果只发送了部分数据,继续发送下面的数据,recv一样的道理
icemoon1987 2008-07-21
  • 打赏
  • 举报
回复
谢谢啊,不过我刚开始学,还不太会用。
能不能再说得稍微详细一些呢,谢谢。
不麻烦你帮忙写代码,只要讲一下思路就可以了。另外能告诉我该去看书上的那一部分相关知识吗?
thirddata 2008-07-21
  • 打赏
  • 举报
回复
这样的代码,当然那有问题了
1,每个send函数的返回值
2,每个recv函数的返回值
3,如果send函数返回的值没有发送完所有数据,需要再次发送剩余数据。
检查一下啊
icemoon1987 2008-07-21
  • 打赏
  • 举报
回复
谢谢啊,我刚开始学,对于Socket和TCP的理解还很浅。

我用一个Send语句传送文件,是系统自动把这个文件分成很多份在打包发送的吗??

如果是的话,是不是接收后系统自动在把这些包组合起来?
我应该怎样才能加上验证呢?

不麻烦你帮忙写代码,只要讲一下思路就可以了。另外能告诉我该去看书上的那一部分相关知识吗?
我想把这个问题弄清楚。

再次谢谢了!
ouyh12345 2008-07-21
  • 打赏
  • 举报
回复
用非阻塞的socket,循环读、写
西山小月 2008-07-21
  • 打赏
  • 举报
回复
最好加上一些验证,每个包都有序号

18,363

社区成员

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

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