我是一名刚开始学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();

}

解决方案 »

  1.   

    用非阻塞的socket,循环读、写
      

  2.   

    谢谢啊,我刚开始学,对于Socket和TCP的理解还很浅。我用一个Send语句传送文件,是系统自动把这个文件分成很多份在打包发送的吗??如果是的话,是不是接收后系统自动在把这些包组合起来?
    我应该怎样才能加上验证呢?不麻烦你帮忙写代码,只要讲一下思路就可以了。另外能告诉我该去看书上的那一部分相关知识吗?
    我想把这个问题弄清楚。再次谢谢了!
      

  3.   

    这样的代码,当然那有问题了
    1,每个send函数的返回值
    2,每个recv函数的返回值
    3,如果send函数返回的值没有发送完所有数据,需要再次发送剩余数据。
    检查一下啊
      

  4.   

    系统不会帮你分包的,你应该检查send的返回值,看看是否所有数据都发送了,如果只发送了部分数据,继续发送下面的数据,recv一样的道理
      

  5.   

    比如你发送char szBuffer[1024],
    调用一次send,send返回512,说明这次send只发送成功了512字节
    应该再次调用send,发送下面的512字节,
    去看msdn
      

  6.   

    恩,是不是一个Send函数一次发送的数据有个最大限制啊?如果要再次发送剩余数据的话,我怎么知道刚才发送到哪儿了呢?不好意思啊,我是个初学者,还什么多不太懂。能不能麻烦你说的详细一点?
    谢谢了!
      

  7.   

    哦,太谢谢了。我大概有思路了。
    但是现在还不明白一个地方。
    Send函数有三个参数,我要怎样确定它从那个字节开始发呢?
    还是我把没发完的数据再放入另一个缓冲区,然后调用Send发送呢?
    另外recv函数,要怎么样才能控制它接收了数据后加入刚才的缓冲区后面呢?
    还是我要重新开辟一片缓冲区,然后接受完后,再连接起来?
      

  8.   

    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;
         }
       }