Client:         long start=GetTickCount();
CFile file;
file.Open("readme.txt",CFile::modeRead);
int length=0;
char buffer[1024];
while(length=file.Read(buffer,1023))
{
m_ClientSocket.Send(buffer,length);
}
file.Close();
char cmd[5]={0};
strcpy(cmd,"ends");
m_ClientSocket.Send(cmd,strlen(cmd));
long ends=GetTickCount();
char buff[64]={0};
sprintf(buff,"All Take: %ld ticks",ends-start);
MessageBox(buff);
这段代码是读出readme.txt这个文件并发送出去.
发送完毕后发一个ends命令,说明这个文件已发送完毕.Server:         CFile file;
         file.Open("test.txt",CFile::modeCreate|CFile::modeWrite);
      以下是OnReceive(int nErrorCode) 
         char buff[1024];
int bufflen=1024;
int nLen = CSocket::Receive(buff,bufflen);
         call AddMsg(char* buffer,int nLen)void CServerDlg::AddMsg(char* buffer,int nLen)
{
buffer[nLen]=NULL;
if(!strcmp(buffer,"ends"))
{
file.Close();
return ;
}
else
file.Write(buffer,nLen);
}
这样子test.txt文件里居然包含了ends这个字符,怪.
我基础不是很好,请大家帮我看看是哪里出了错.

解决方案 »

  1.   

    应该是粘包了.
    建议象这样连续发送TCP包应该通过明确定义来生成包边界. 接收方通过检测这些边界来得到跟服务器端相同的包结构
      

  2.   

    嘿嘿,还真有这种说法的哦:
    无论使用阻塞方式或非阻塞方式编程,需要重点考虑的一个问题:粘包现象,即应用发送两个或以上的数据包,在Socket通讯层将数据包合并成一个发送出去,因此接收端收到数据包以后需要对数据包根据应用定义的长度进行拆分,否则导致应用层丢包。
      

  3.   

    void CServerSocket::OnReceive(int nErrorCode) 
    {
    // TODO: Add your specialized code here and/or call the base class
    // TODO: Add your specialized code here and/or call the base class
    int bufflen=20484;
    int nLen = CSocket::Receive(buffer+receptr,bufflen);
    reclength+=nLen;
    packlength=*(int*)buffer+sizeof(int);  
    if(reclength>=packlength)
    {
    AnalysePacket(buffer,reclength); //包完整了,分析......
    }
    else                            //所发送的包未完整
    {
    receptr=receptr+nLen;  //返回继续接收包
    }
    CSocket::OnReceive(nErrorCode);
    }void CServerSocket::AnalysePacket(char *buffptr,int len)
    {
    int length=len;
    CServerDlg *dlg;
    dlg=(CServerDlg*)AfxGetApp()->m_pMainWnd;
    int allpack=0;
    int packetsize=0;
    int indicator=0;
    while(1)
    {
    packetsize=*(int*)(buffptr+indicator);//取得包长度
    allpack=allpack+packetsize+sizeof(int);//所有包长度
    dlg->AddMsg(buffptr+indicator+sizeof(int),packetsize);//处理这些数据吧
    indicator=indicator+packetsize+sizeof(int);
    reclength-=packetsize;
    len=len-(packetsize+sizeof(int));//剩余数据长度
    if(!len)//这么巧,刚好是一个完整的包
    {
    reclength=0;
    receptr=0;
    return;
    }
    int lastpacketsize=*(int*)(buffptr+indicator);//取得下一个包的大小
    if(lastpacketsize>len)//不是完整的包?
    {
    for(int i=0;i<(length-indicator);i++)
    {
    *(buffer+i)=*(buffer+indicator+i);//把这些数据搬到缓冲区最前
    }
    receptr=len;
    reclength=receptr;//把缓冲区指针设到这些数据后面
    return;//继续接收数据
    } }
    }
    人老了,写代码也艰难了.
      

  4.   

    确实会出现这样的问题。服务器可能会把文件内容和结束标志一起发送出去,而客户端(异步)接收到的可能是两者连在一起。或者向楼上那样把所有的数据接收结束然后去分析数据,还有就是把数据和控制的发送分开(就像FTP那样有两个通道,一个用于数据、一个用于控制命令)。