我利用CSocket发送了一段消息,以“M”开头,然后发有效数据,最后发结束符“N”。
接收函数为
int CTestDlg::ReceiveFileMsg(CSocket &recSo, SOCKADDR_IN &client)
{
    m_Output.ResetContent();
if(m_type=='M') //在监听线程里我已经判断了消息头
{
char buff[100]={0};
CString msg;
int ret=0;
for(;;)
{
ret=recSo.Receive(buff,100);
if(ret==0)
break;
msg+=buff;
}
CString strOut,strIn;
m_You_IP.GetWindowText(strIn);
GetNamebyAddress(strIn,strOut);
CString youName;
youName.Format(inet_ntoa(client.sin_addr));
CString str=youName+"<-"+strOut;
AddMsgList(str,msg);
Strtok(msg);
}
recSo.Close();
return 0;
}
因为有的时候数据量很大,远远大于100个字符,所以得设置个循环,同时我加了个结束符,现在的问题是怎么写这个循环,判断条件是最后一个字符“N”????

解决方案 »

  1.   

    bool CTestDlg::ReceiveFileMsg()
    {
       char buf[MAX];
       int nRet=recv(hSocket,buf,MAX,0);   if(strcmp(buf[0],'!')==0) //接收到的第1个字符为'!';
       if(strcmp(buf[nRet-1],'#')==0) //接收到的最后一个字符为'#'号
    }最好不要 m n  这样的字符    要用特殊点的  比如上面的 !  # 号等
      

  2.   

    流是没有边界的,可能你发两个包,Receive一次就全收了
    所以你可以自己定义自己的协议啊,比如第一个字节是一个标示位,第二个是这个包的长度
    你先recv第一个字节,看看是不是你的包,如果是,你再recv一个字节,看看是不是你定义的长度,如果是,那就recv这个长度的字节...
      

  3.   

    流是没有边界的,可能你发两个包,Receive一次就全收了
    -----------------------
    那样就是包粘住了    这样包不完整的可能就2种(不完整指收到的包的内容与实际发送的包的内容大了 或小了 )
    1:粘包(A:发送端由于发送数据时数据量太小 B:接收端由于接收的时候系统繁忙 导致FD_READ事件被阻碍  这样包也粘住了)
    2:如果发送端发送的包大过系统最大允许的大小   那么系统帮你分包  1包变N包  
      或缓冲区塞满了(接收端跟发送端都有可能)  
    上面的问题几个语句就可以解决  为什么不能用起始结束字符
      

  4.   

    那就是M和N之间,不可能在有M或者N了,要不然起始/结束就会误判
      

  5.   

    wqrz_015的观点很奇怪啊,不知道你是怎么做协议呢?居然能用文字当起止位置的判断?OMG
      

  6.   

    OMG??
    你去翻翻传奇的代码   人家就那样干的  难道写传奇协议的人会差劲到这个地步??
      

  7.   

    特大量的高速数据处理比较适合采用边界办法,
    你从单个线程的角度考虑,大量的数据包到达时:
    第一你的CPU性能的利用率会高上几十倍;第二至少你不需要为这些数据包准备对应的缓存当然,实际上情况不能理解的这么简单,单通常来说
    你的计算能力绰绰有余的时候,比较多考虑帧长度的办法
    计算能力捉襟见肘的时候,那就考虑边界的办法吧
      

  8.   

    to wqrz_015() 如你所说,虽然网络游戏我不怎么玩,但这个游戏的网络传输部分真可以说是垃圾了(连扩展的余地都没留,失败),要知道即使这个游戏整体水平NB,也不能说明它的一切都是NB的啊?wqrz_015()的逻辑很奇怪呢,按你的逻辑推理,经常有人说linux很NB,那它的界面易操作性也比windows强?哈哈。小家伙看问题别那么绝对了,无论有怎样的高手使用过这一方法,也不能说明这个方法本身好,老老实实定义自己的协议才素做通讯的王道