我要在网络中传输文件,下面是我的服务器端接收代码和客户端的发送代码,可是当文件小的时候〔比如200字节时〕服务器端就无法接收到该文件,不知道问题出在那里。(第一次进行网络编程,可是这是一个项目的内容所以很急)
DataBufLen = 512服务器端代码:当有客户端发送上传文件请求后调用该函数BOOL CServerApp::SaveFile(SOCKET &s, CDataStream &data)
{
char buf[DataBufLen] = {0};
int retval = 0;
int retval_count = 0;
CFile sfile; if (!sfile.Open(DISKPATH + data.Path,CFile::modeCreate|CFile::modeWrite))
return -1; while(TRUE)
{
retval = recv(s,buf,DataBufLen,0);

if(retval_count==data.FileSize) {
sfile.Write(buf,retval);
break;
}

if(retval == 0) break; retval_count+=retval;
sfile.Write(buf,retval);
} sfile.Close();

if(retval_count != data.FileSize)
{
AfxMessageBox("error");
DeleteFile(DISKPATH + data.Path);
return FALSE;
}
return TRUE;
}
客户端代码:思路是先发送文件信息,如文件长度,名称等 CFile sfile;
// 以二进制的形式打开指定的文件
if(!sfile.Open("e:\\temp\\temp1.txt", CFile::modeRead))
{
*Result = 0;
return S_FALSE;
} fdata.FileSize   = sfile.GetLength(); // 文件长度 
fdata.PackToBuf(); // 打包文件信息 int return_value = 0;
// 先把文件信息发送给服务器,服务器端接收到后准备接收文件
return_value=send(m_Sock,fdata.szBuf,fdata.num,0); 

if(return_value==SOCKET_ERROR)
{
*Result = GetLastError();
return S_FALSE;
} char buf[DataBufLen] = {0};
int temp = 0 , end = 0 ,num = 0;
sfile.Seek(0,CFile::begin); while(TRUE)
{
 
num=sfile.Read(buf, DataBufLen);
if(num == 0) 
{
break;
}
end = send(m_Sock,buf,num,0); temp+=end; if(end==SOCKET_ERROR)
{
*Result = GetLastError();
break;
}
}
sfile.Close();
// shutdown(m_Sock,2);
closesocket(m_Sock);

解决方案 »

  1.   

    程序好象本来就不对嘛,因为你客户端当最后一块文件send出去以后,就执行了sfile.Close();shutdown(m_Sock,2);closesocket(m_Sock);
    而服务器的recv正好在客户端socket关闭后才执行,则返回值应该是0(或者是错误码),所以就回跳出循环(或者循环等待)当然就不会写入文件了,你处理的办法是文件最后发出后,加入延时或给客户端发一个结束消息。
      

  2.   

    你看你自己的代码流程就知道了,小文件的话客户端send文件信息头以后立刻就send数据然后就关闭,而服务器在接到信息头以后,还要做文件的创建或打开工作(耗时比send要长)然后等到执行到recv时,客户端这时已经关闭了。
    而大文件的话客户端send文件信息头以后就send数据,在此期间服务器在接到信息头,做文件的创建或打开工作,然后执行recv而,客户端之前send来的数据都在缓冲区内,所以recv的执行要比send快,recv完缓冲区的数据后,客户端和服务器端达到了同步,当客户端发完最后一块数据后执行sfile.close(),在执行这句的时候,服务器执行recv语句,当sfile.close执行完成后,recv早已取出了数据。所以会保存成功
      

  3.   

    windbells(风铃哦 谢谢,可以留下联系方式吗?以后有问题在联系。。谢谢
      

  4.   

    qq 16822065
    简单的解决话就是发完最后一块后Sleep()一下,估计有个500毫秒足够了,
    如果想解决的好一点话,整个传输程序都要改,如果是作为文件服务器的话就要采用多线程,
    数据包里加入文件偏移信息等数据,以便能支持断点续传。如果点对点的话,你只需要每发送完发送一个应答信息就可以了。等客户端收到应答确认后继续发下一个数据包,
    数据包在逻辑结构也可分为三层:传输层和对话层,数据层。
    传输层中记录数据包大小,CRC32校验和,对话层包括文件的数据信息。数据层保存包的数据。
    每层校验通过后提交上一层处理
      

  5.   

    谢谢大家了,太好了Richard2003(谫) 留下qq好吗