服务器端采用WSAAsyncSelect模型,对客户端发送过来的数据进行处理。
客户端要向服务器端发送数据请求,数据组织成一定的报文格式发送,报文头中包含了此次发送的请求类型和报文长度,然后客户端用send函数把整个报文发送出去,由于报文可能很长,因此采用循环发送。服务器端在FD_READ的响应中先接收报文头,然后根据报文类型进行不同的处理,在这些不同的处理中根据报文头中的报文长度读取整个报文。问题是当客户端一次send发送不完整个报文时,在服务器端的处理中根据报文头中的长度信息能直接读取到整个报文吗?还是需要在另外一个FD_READ之后才能读取到呢?

解决方案 »

  1.   

    可以循环等待接收,但这样浪费效率,最好是等下次FD_READ再继续接收。
      

  2.   

    如果服务器socket上的数据,如果你没有recv或没有recv完,则那个socket的状态,一直是FD_READ的,也就是说只要socket的buffer中的数据没有读取完,你用select函数来检查,则他永远的是FD_READ的,这跟你客户端调用多少次send是没有关系的。
      

  3.   

    case FD_READ:
    {
       recv();                          //接收报文头
       ……                             //处理报文头,得到报文类型和总的报文长度
       case type:                           //根据不同报文类型进行处理
            {
              while(1)
                {
                   recv();         //循环读取整个报文。      此时客户端发送的报文并不是一个完整的报文,那在此处循环接收报文头中所表示的报文长度的报文,是否能
                                                                     接收到完整的报文呢?

                 } 
             }
    }
      

  4.   

    当然可以,recv只是一个copy的动作,但这样的缺点就是比较损耗cpu,如果一直没哟数据,cpu将在那里空转
      

  5.   


    的确是啊。但我每次send都发送整个数据,服务器端接受完整个数据后就退出循环了,cpu应该不会等太长时间的吧
      

  6.   

    时间主要受网络环境影响,通常不会等太长时间,但还是浪费了,如果程序没有其它任务要处理,可以在循环中加上一行Sleep,降低CPU使用率。
      

  7.   


    你没弄清楚何谓"异步".如果没接收完的数据还没到达,你循环调用recv(),一样是没有数据接收到,recv()只会不断地返回错误,最大的问题是,你这样做已经破坏了"异步"的执行环境,将"异步"弄成了阻塞,在你的while()循环中,系统其它消息,象有数据可接收的FD_READ等消息你的程序都没法接收到.正确做法是当第一次没能接收完,等待下一个FD_READ消息,然后在第一次没接完的buffer后追加.例如第一次接收了50 bytes,那么第二次接收就是SessionCurrent->DataBuf.buf = &SessionCurrent->Buffer[50];
    SessionCurrent->DataBuf.len = sizeof(SessionCurrent->Buffer) - 50;
    if (WSARecv(hSocket, &(SessionCurrent->DataBuf),1, &RecvBytes,&Flags, NULL, NULL) == SOCKET_ERROR)第二次再接不完,继续象上面的追加就是.一直追回到接完为止就是.