我用CAsyncSocket写了一个服务器端和客户端的程序,想让客户端把文件传输到服务器端。这个程序是异步非阻塞的。
客户端的OnSend(int nErrorCode)函数里有个while循环,如果发送的字节数小于文件长度就一直ReadFile()并Send()
服务器端的OnReceive(int nErrorCode)函数里也有个while循环,如果写进文件中的字节数小于文件长度就一直Receive()并WriteFile()。
我用断点调试,一边发一边收没什么问题,但是让两边程序都运行,客户端发送文件,总是发不完全,比如600K的文件到服务器端只有60K。小点的文件就没有问题,比如3K左右的txt文件能完好发送。问题出在哪儿?是不是收发速度不协调导致的?
客户端的OnSend是通过一个FD_WRITE来调用的。
本人超级菜鸟啊。PS:本人没有分,好像只有5分了希望有人能慷慨相助

解决方案 »

  1.   

    你可以sleep一下,看看是不是速度的问题
    要是让我写客户端的文件发送到服务器,我会采用阻塞的方式,单独地开通一条线程用来处理文件的发送,我曾做试过,用的是TCP。发送几百M,甚至几G的数据都不会出错
      

  2.   

    发送数据,本身不存在所谓的速度问题,凡是出错的都是你的代码处理有问题,有人说用同步发送可靠,实际是一样的,我写代码时,肯定都是选择异步来处理的.所以这是个误区,大家必须避免这样的想法.你发送时可以先从文件取一段数据,而后对这段buf进行数据发送,send后判断发送了多少,而后循环至buf发送完,而后在继续readfile,如此往复,直到发送完毕.
      

  3.   

    我把我OnSend()和OnReceive()代码贴出来,大家帮我看看吧void CSendFileSocket::OnSend(int nErrorCode)
    {
    // TODO: Add your specialized code here and/or call the base class
    if(nErrorCode==0)
    {
    DWORD dwRead=0;    //每次从文件中读出的字节数
    DWORD ret=0;       //每次Send字节数
    DWORD idx=0;       //Send的控制游标
    char * data=new char[2048];      //数据缓冲区
    if(dwBytesRead==0)          //dwBytesRead为总Send字节数      
    {
    _CreateFile();      //创建要发送文件的句柄
    SendFileDataStruct();     //把文件信息先传过去
    }
    if(hFile==INVALID_HANDLE_VALUE)
    {
    return;
    }
    while(dwBytesRead<m_FileLength)
                    {
    memset(data,0,2048);
    idx=0;
    if(false==ReadFile(hFile,data,2048,&dwRead,NULL))           //...
    {
    CloseHandle(hFile);
    return;
    }
    while(dwRead>0)
    {
    ret=Send(data+idx,dwRead);
    if(ret==SOCKET_ERROR)
    break;
    dwRead-=ret;
    idx+=ret;
    dwBytesRead+=ret;
    }
    }
    if(dwBytesRead==m_FileLength)
    {
    delete [] data;
    CloseHandle(hFile);
    }
    }
    CAsyncSocket::OnSend(nErrorCode);
    }
      

  4.   

    void CReceiveFileSocket::OnReceive(int nErrorCode)
    {
    // TODO: Add your specialized code here and/or call the base class
    if(nErrorCode==0) 
    {
    DWORD dwWrite=0;
    DWORD ret=0;
    char * data=new char[4096];
    if(dwBytesWrite==0)
    {
    AcceptFileDataStruct();
    _CreateFile();
    }
    if(hFile==INVALID_HANDLE_VALUE)
    {
    return;
    }
    while(dwBytesWrite<Stream_File_Info.nFileSizeLow)
            {
    memset(data,0,4096);
    dwWrite=0;
    DWORD nLeft=2048;
    DWORD idx=0;
    if((Stream_File_Info.nFileSizeLow-dwBytesWrite)>=2048)
    while(nLeft>0)
    {
    ret=Receive(data+idx,nLeft);
    if(ret==SOCKET_ERROR)
    break;
    idx+=ret;
    nLeft-=ret;
    }
    else
    ret=Receive(data,Stream_File_Info.nFileSizeLow-dwBytesWrite);
    if(ret>0)
    {   while(dwWrite<ret)
    {
    if(false==WriteFile(hFile,data+dwWrite,ret-dwWrite,&dwWrite,NULL))
    {
    CloseHandle(hFile);           //!!!!!!!!!!!!!!!!!!!!!!
    return;
    }
    }
    dwBytesWrite+=ret;
    }
    else
    break;
    }
    if(dwBytesWrite==Stream_File_Info.nFileSizeLow)
    {
    delete [] data;
    SetFileTime((HANDLE)hFile,
         &Stream_File_Info.ftCreationTime,
                             &Stream_File_Info.ftLastAccessTime,
                             &Stream_File_Info.ftLastWriteTime);
    SetFileAttributes(Stream_File_Info.szFileTitle,
          Stream_File_Info.dwFileAttributes);
    CloseHandle(hFile);
    }

    }
    CAsyncSocket::OnReceive(nErrorCode);
    }
      

  5.   

    jwybobo2007,我Client就是按你的描述写的,我想问一下,这种情况Server接收的策略是怎么样的?Client这样子一直写会不会造成计算机内部缓冲区溢满
      

  6.   

    我也碰到过这样的问题,用SLEEP()完全没用,可以用这样的办法:
    发送端发送完一次数据后,等待对方接收数据并回复一个响应后再继续发下一次数据。也就是说增加一个
    确认机制,接收端在接收到数据后给发送端一个确认响应。这样就不会出现逆说的收发不一致的现象。