代码如下:
发送端: byte buffer[1024*16]; //分段传输,每段16K
int iCount;
while(1)
{
iCount = file.Read(buffer,1024*16);//读取文件,每次读取16K
if(iCount < 1024*16)  //如果存在某段小于16K,则此段为最后一段
{
    msg.m_wType = PACKAGE_FILE_RESPONSE_COMPLETE;
TRACE1("Send %d\n",iCount);
}
else    //等于16K,继续发送下一段
{
msg.m_wType = PACKAGE_FILE_RESPONSE;
TRACE1("Send %d\n",iCount);
}
                                    msg.m_sBuffer = buffer;
m_pSessionSocket->SendMsg(&msg);//发送
if(msg.m_wType == PACKAGE_FILE_RESPONSE_COMPLETE)
break;
}
接收端: static BOOL bOpen = FALSE; //文件是否打开
if(msg.m_wType == PACKAGE_FILE_RESPONSE) //不是最后一段
{
if(!bOpen) 
{ int pos = m_DownFileList[0].ReverseFind('\\');
CString sFilePath = m_DownFileList[0].Mid(pos+1);
sFilePath = "E:\\" + sFilePath;           //取文件名

if(!m_file.Open(sFilePath,CFile::modeWrite|CFile::modeCreate))
{
MessageBox("Failed to Open the file!");
}
SetWindowText("正在传输文件"+m_DownFileList[0] + "...");
bOpen = TRUE;
}
m_file.Write(msg.m_sBuffer,msg.m_sBuffer.GetLength());
TRACE1("Receive %d\n",msg.m_sBuffer.GetLength()); //每次接收大小只有2到3K
return;
}

if(msg.m_wType == PACKAGE_FILE_RESPONSE_COMPLETE) //最后一段
{
m_file.Write(msg.m_sBuffer,msg.m_sBuffer.GetLength());
TRACE1("Receive %d\n",msg.m_sBuffer.GetLength());
m_file.Close();
SetWindowText(m_DownFileList[0] + "下载完毕!");  
bOpen = FALSE;
}
问题:
发送端可以按每段16K发送,但是接收端每次接收不到16K,总是2到3K,望高手解决!在线等。。

解决方案 »

  1.   

    与接受缓冲区大小和MSS(最大报文段大小)有关,默认缓冲区大小为4K。
    lz实验的环境下,MSS应该为1K。 受接收端应用程序的接收速度影响(这里网络速率等因素暂不考虑),收到的数据大小在1K~4K之间。收方比发方慢,那么基本上收到4K大小,发方和收方速度差不多,那么基本就是2K~3K大小,收方比发方快,那基本就是收到1K。另外,发送时,每次send的大小不是16K,lz不要认为16k是一个包发出去的。这个和MSS有关。tcp层每次发送MSS大小的包
      

  2.   

    tcp是流协议。
    在lz现在设计的基础上修改的话,msg里应该再加个字段,发送的数据长度。
    接收方应该开辟一个比较大的buffer,至少32K大小。将接受到的数据放到buffer里,
    当buffer内的数据长度 >= msg各个字段的大小+发送的数据长度  时,则取出完整的msg内容,然后将文件的数据写入文件。以上的方式做个简单的文件传输试验是可以的。对于真正要用tcp来做项目的时候,应当定义包的结构,包头,包尾,指令标识,包的数据长度,数据,数据的CRC校验等等, 数据部分还要根据不同的指令定义相应的结构
      

  3.   

    在windows中,SOCKET的接受缓冲区大小默认是8k,你每次发送16k,客户端肯定接收不完整。使用setsockopt函数进行设置
      

  4.   

    5楼说的有点道理,但是我照你说的还是做不来,如果使用CSocketFile,如何设置接受端每次接收的大小?我在网上看到别人一般都是直接使用CSocket的Send和Receive进行发送和接收,那样可以设置每次接收缓冲区的大小,发送端和接收端保持一样就可以发送大型文件。
      

  5.   

    我也做了CSocket的文件传输 可以供你参考 给个邮箱 或去这里下载http://download.csdn.net/source/2373543
      

  6.   

    m_file.Write(msg.m_sBuffer,msg.m_sBuffer.GetLength());
    除了上面的问题外,这句话也有问题。msg.m_sBuffer.GetLength(),如果是非文本文件GetLength()显然不对。建议在文件包里再添加一个buff长度变量即每次read的大小。