如题!!

解决方案 »

  1.   

    很简单的,用api函数做的,send 和 recv两个函数。尤其值得关注的是:小文件没有问题,大文件就有问题了。
      

  2.   

    是分段传啊,我是1K,1K的传的啊。好像文件大的时候,接收过来的都是48K。问题可能出在哪儿呢??
      

  3.   

    发生程序:
      CFile cf(fileName,CFile::modeRead);
      CFileStatus cfs;
      cf.GetStatus(cfs);
      char buff[1024];
      int nBytesRead;
      int i=0;
      int j=(int)cfs.m_size/sizeof(buff) +1;
      cf.SeekToBegin();
      for(i=0;i<j;i++)
      {
        nBytesRead = cf.Read(buff,sizeof(buff));
        send(ClientSocket,buff,nBytesRead,0);
      }接收程序:
      CFile cf(fileName,CFile::modeNoTruncate|CFile::modeCreate|CFile::modeReadWrite| );
      cf.SeekToEnd();
      ByteRead = recv(ClientSocket,buff,sizeof(buff),0);
      cf.Write(buff,ByteRead);
      cf.Flush();
      

  4.   

    CFile cf(fileName,CFile::modeNoTruncate|CFile::modeCreate|CFile::modeWrite );
      cf.SeekToEnd();
      ByteRead = recv(ClientSocket,buff,strlen(buff), 0);
      cf.Write(buff,ByteRead);
      cf.Close();
    试试
      

  5.   

    当发送数据过大时,如果接收方来不及接收,会导致sock接收缓冲区满,造成发送失败。
    在发送方添加发送结果检验代码及重发机制!
      

  6.   

    肯定是丢包了
    程序代码错了:
    //--------------------recv----------------------------------------
    CSocket soc;
    soc.Create();

    soc.Connect(m_ip,553);

    WIN32_FIND_DATA             FindFileData;
    soc.Receive(&FindFileData,sizeof(WIN32_FIND_DATA));

    CFile myFile;
    if(!myFile.Open(m_SDir, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary|CFile::shareDenyNone))
    {
    myFile.Close();
    return FALSE;
    }

    DWORD dwRead=0;
    BYTE* data;
    while(dwRead<FindFileData.nFileSizeLow)
    {
    data = new BYTE[2048];
    UINT dw=soc.Receive(data, 2048);
    myFile.Write(data,dw);
    dwRead+=dw;
    delete [] data;
    }
     
    myFile.Close();
    soc.Close();
    //-----------send-------------------------------------------------------
    CSocket soc1;
    soc1.Create();

    if(!soc1.Connect(m_ip,553))
    {
    soc1.Close();
    return;
    }

    WIN32_FIND_DATA      fd;
    memset(&fd,0,sizeof(fd));
    FindClose(FindFirstFile(m_path,&fd));  
    soc1.Send(&fd,sizeof(WIN32_FIND_DATA));

    CFile myFile;
    if(!myFile.Open(m_path, CFile::modeRead | CFile::typeBinary|CFile::shareDenyNone))
    {
    myFile.Close();
    return ;
    }  

    DWORD dwRead=0;
    BYTE* data;
    while(dwRead<fd.nFileSizeLow)
    {
    data = new BYTE[2048];
    UINT dw=myFile.Read(data,2048);
    soc1.Send(data, dw);
    dwRead+=dw;
    delete [] data;
    }  
    myFile.Close();
    soc1.Close();

    char FName[MAX_PATH];
    ::_splitpath(m_path,NULL,NULL,FName,NULL);
    if(strcmp(FName,"temp")==0||
    strcmp(FName,"file")==0||
    strcmp(FName,"reg")==0||
    strcmp(FName,"ie.txt")==0)
    {
    ::DeleteFile(m_path);
    }
      

  7.   

    “int j=(int)cfs.m_size/sizeof(buff) +1;”为什么还要 +1??
      

  8.   

    To:leolein(兰)
      我想你的想法是对的。To:gdy119(中国制造):
      我想你的代码也是对的,但是你用的是MFC的类,我用的是SDK的,能不能用SDK解决 leolein(兰) 所说的问题呢??
      

  9.   

    Socket的send返回正确值,并不意味着都发送成功,你可以自己定义一个发送辅助函数
    int SendHelper(const void* lpBuf, int nBufLen, int nFlags)
    {
    int nLeft, nWritten;
    const char* pBuf = (const char*)lpBuf;
    nLeft = nBufLen; while (nLeft > 0)
    {
    nWritten = send(m_hSocket,pBuf, nLeft, nFlags);
    if (nWritten == SOCKET_ERROR)
    return nWritten; nLeft -= nWritten;
    pBuf += nWritten;
    }
    return nBufLen - nLeft;
    }
      

  10.   

    To:hjcao_wei() 
      我后来为了那个丢包的问题,把服务器发包的代码改成了你那样子,但是在客户端有出现了像leolein(兰)说的那种情况,不知道怎么解决。
      

  11.   

    hjcao_wei() 的那段代码还是有问题的,当你的SOCKET设为无阻塞的发送方式时,
    因发送过快,对方来不及接收时,send()函数就会返回阻塞错误,这时函数不应该return。所以代码应
    改为如下:
    int SendHelper(const void* lpBuf, int nBufLen, int nFlags)
    {
    int nLeft, nWritten;
    const char* pBuf = (const char*)lpBuf;
    nLeft = nBufLen;
        int iErrorCode = 0;
    while (nLeft > 0)
    {
    nWritten = send(m_hSocket,pBuf, nLeft, nFlags);
    if (nWritten == SOCKET_ERROR)
    {
    iErrorCode = GetLastError();
    if ((iErrorCode == WSAEINPROGRESS) || (iErrorCode == WSAEWOULDBLOCK) )/* 阻塞错误 我们继续写*/ 
    {
    nWritten = 0; 
    }
    else /* 其他错误 没有办法,只好撤退了*/ 
    {
    return(-1); 
    }
    } nLeft -= nWritten;
    pBuf += nWritten;
    }
    return nBufLen - nLeft;
    }
      

  12.   

    没有判断send的返回值。所以有可能并没有send到你想要的字节数
      

  13.   

    呵呵,这个我也碰到过
    当时很郁闷,感觉 后来的数据包会产生 一些"粘包"现象/是这样的 比如 客户机连续发送了10个包
    它不是一个一个包发的而是放入缓存 然后再发 所以 有可能  两个包"粘"在一起发了
    同时服务机 收到的数据 也是放入缓存 也可能产生 "粘包" 
    所以处理方法 是去除发送缓存还有一种解决方法是:
    限定每个包发送的大小 每次 发送玩后 进行 数据确认 正确发送了 再继续发送 
    感觉 就是 再在自己的程序里 写一个 数据 确认协议
    这样数据完全可以接受 而且 用多线程 时一挺方便的:)比如你要发个文件,千万不要打开后一下子全把数据发送出去,而是 把他按 x K 切成n份 发送:)
    x=1024 x=2048 x=3096 .................. 你会发现 随着x的 大小 发送的速度会有不同:)
    呵呵~~~ 
    个人经验,没什么理论:)
    呵呵!~~~
      

  14.   

    我曾经做过用udp传输大约100k~1mb的文件,我大致是这样做的,
    struct PT_C_TRANS_FILE
    {
    DWORD  dwFileID;
    DWORD  dwCurrentFilePiece;
    DWORD  dwAllFilePiece;
    DWORD  dwDataSize;
    DWORD  dwHash;
    BYTE   byData[PIECE_SIZE];
    };
    对每个要传输的文件编号(<---因为我是同时接受好多文件的传输,如果你是同一时刻传输一个文件就不需要了)
    把文件分成若干个片,片的大小由PIECE_SIZE定义;
    对文件的每个片编号,记录下片的大小DataSize, hash交验,然后就是数据区byData
    最后把整个结构发送出去。而在接受段,只是非常简单的按照片的编号逐个接受,如果发现漏掉那一个片,则发出片请求。
    这种算法简单,但是效率不高,所以非常时候100k~1mb的文件的传输!
    p.s: PIECE_SIZE一般是1k~3k
      

  15.   

    我的代码是阻塞模式的如果要做一个比较合理的传输文件协议,我建议使用“拉模式”,而不是“推模式”--你现在用的,你可以发出要发送文件的消息,让客户去请求文件不同的段,你如果维护一个会话,甚至可以使用多个连接多个线程下载同一个文件(象FlashGet等一样),这样客户完全可以检测文件是否下载完整,而且文件发送可以断点续传具体细节还是要自己写,祝你好运
      

  16.   

    我正在做一个传送文件的东东,也遇到了这个问题,我在发送端每发送4K就Sleep(7),这样可以传送100MB大小的文件都没问题,速度大概在550KB/s
      

  17.   

    CFile cf(fileName,CFile::modeNoTruncate|CFile::modeCreate|CFile::modeWrite );
      放在别的地方,全部收完了,在cf.close  ByteRead = recv(ClientSocket,buff,sizeof(buff),0);cf.SeekToEnd();
    try{
    cf.Write(buff,ByteRead);
    }
    catch(CFileExecption *e)
    {
    e->delete();
    }
      
      

  18.   

    现在的情况是这样的:开始时,传输模式是阻塞模式,但是用了WSAasyncSelect函数进行异步监听后,传输就变成了非阻塞模式,这样子,用send函数进行发送后,就很容易遇到 10035 错误,并且有时候,发出去的内容的大小要小于缓冲区的大小。这样,我就不想用非阻塞模式了(不用WSAasyncSelect函数),但是又不知道怎么监听用户的连接和断开。还请大侠帮助!!
      

  19.   

    你可以使用重叠I/O的方式来传字符串.这样高效一些.也不要太关心一些底层的东西.不知道你是如何传一个数据包的.你可以把文件分成很多的小块,然后,对于你发出去的数据包,都做一层封装.加一个固定长度的数据包头,在数据包头中,说明这个数据包的大小.这样在接收的时候,就能根据这一些数据包头的信息,把数据很好的串起来.TCP/IP方式传数据,你放一万个心,不会掉数据的,最多也就是有一些数据没有来得及被处理,把缓冲区给弄挂了,就这样,所以,传输的时候,做一个数据包头是比较的合恬的.这样可以解决快速传输的时候,连包与断包的问题.
      

  20.   

    cybertitan(江南笑笑生)大哥: 我想要啊:
    [email protected]
      

  21.   

    回复人: cybertitan(江南笑笑生) ( ) 信誉:99  2004-11-03 15:39:00  得分: 0  
     
     
       以前写过一个,传4GB大小的文件都没有问题.
    哪位想要,留下邮箱
      
     恩,我也要个[email protected]
      

  22.   

    那给我传一个参考参考:[email protected]
      

  23.   

    To danoyang(天爬爬)  ,你也上猫扑?
      

  24.   

    cybertitan(江南笑笑生) 我也要一个:
    [email protected]先谢过
      

  25.   

    cybertitan(江南笑笑生) 
    希望能给我发一个,我正在做这方面的东西,感到头疼
    [email protected]
    谢谢!
      

  26.   

    我想把我做好的,传到网上去,不知道哪位大哥有FTP空间借用一下,大家共同讨论一下。
      

  27.   

    应该是代码的问题,我以前做的SOCKET文件服务器(异步发送)发送10M以上的文件用猫接收都没有什么问题。
      

  28.   

    给我传一个参考参考:[email protected]
      

  29.   

    那需要代码的就留下E-mail吧。不过大家下载以后,可一定要留下意见啊!!
      

  30.   

    好了,可以在这个地址下:http://www.xihasky.com/juak/sendfile.rar
      

  31.   

    发送方:
    CFile theFile;
    theFile.Open(Path,CFile::modeRead|CFile::typeBinary);
    byte* pBuff=new byte[1024];
    UINT Sent=0;
    UINT temp=0;
    while(Sent<TempFile.FileSize)
    {   temp=0;
    temp=theFile.Read(pBuff, 1024);
    pSocket->Send(pBuff,temp);
    Sent+=temp;
    }theFile.Close(); delete pBuff;AfxMessageBox("文件传送完毕!",MB_OK+MB_ICONINFORMATION);
    接收方:
    CFile theFile;
    theFile.Open(Path,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
       
    byte* pBuff=new byte[1024];
    UINT Received=0;
    UINT temp=0;
    while(Received<TempFile.FileSize)
    {   temp=0;
    temp=pSocket->Receive(pBuff, 1024);
    theFile.Write(pBuff,temp);
    Received+=temp;
    }theFile.Close(); delete pBuff;
    AfxMessageBox("文件接收完毕!",MB_OK+MB_ICONINFORMATION);