服务器客户端建立链接成功,客户端send数据服务器能接受处理,然后服务器tcpServer->Send调用CTcpServer::Send向客户端发送数据,客服端第一次用recv可以阻塞接受数据,但客服端第二次就不能阻塞接受数据了 请问是什么原因?客户端:
iSend = send(client, (char *)reqPackData, iLen, 0);    第一步:这里先给服务器发送数据iRecv = recv(client, buff, 1024, 0);  第三步:客户端接受到结构数据处理,这里可以阻塞接受
if (reqPackData->ReqNo == ((ReqPack *)buff)->ReqNo)
{
     iRecv = recv(client, buff, 1024, 0); 第五步:应该是接受服务器发送的偏移地址数据,但这步没有阻塞没有接受
}服务器端:
tcpServer->Send(s, (char *)reqPack, sizeof(ReqPack));  第二步:服务器处理数据后调用CTcpServer::Send发送结构数据给客服端
tcpServer->Send(s, pCom+reqPack->dwoffset, reqPack->dwSize); 第四步:服务器发送偏移地址数据给客服端
、、、、、、、、、、、、、、、、、、、、、、、、、、、
int CTcpServer::Send(SOCKET s, char *buf, DWORD size)
{
、、、、、、、、、、、、、、、、、、、、、、、、、、、
     iSend = WSASend(s, &(PerIoData->DataBuf), 1, &SendBytes, Flags, &(PerIoData->Overlapped), NULL);
、、、、、、、、、、、、、、、、、、、、、、、、、、、
}开发环境VC.NET2005 那里人气太差了 借本版宝地  请高手指点

解决方案 »

  1.   

    ((ReqPack *)buff)这个转换 没问题把~~
      

  2.   

    if (reqPackData->ReqNo == ((ReqPack *)buff)->ReqNo)  这步没有问题 我测试通过
      

  3.   

    我看了下,估计是粘包了。
    iRecv = recv(client, buff, 1024, 0);  第三步:客户端接受到结构数据处理,这里可以阻塞接受 
    已经把所有数据发送过来了。
      

  4.   

    给你个方法你自己测试下,在服务端第二次发送数据之前 sleep几秒
      

  5.   

    TO:hopewoo我看了下,估计是粘包了。 
    iRecv = recv(client, buff, 1024, 0);  第三步:客户端接受到结构数据处理,这里可以阻塞接受 
    已经把所有数据发送过来了。
    这里的确阻塞接受了服务器第一次发送的全部数据;我的目的是:服务器第一次(第二步)发送结构数据,客户端第一次用recv(第三步)接受处理,如果这个结构数据正确,客服端第二次用recv(第五步)接受服务器第二次(第四步)发送的偏移地址中的数据,但客服端第二次用recv(第五步)确不能阻塞接受数据了高手们再指点下 非常感谢大家
      

  6.   


    这个我推荐你用流对象来接受,你那个我现在可以肯定是粘包了,没有按照你的想法来发送.
    要解决这个东西,一般推荐用异步的接受,或者用类似BinaryReader 的对象来读取.
      

  7.   

    TO:hopewooclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);iRecv = recv(client, buff, 1024, 0);  中的client就是个流对象
      

  8.   

    client 是什么类型,发我看看
      

  9.   

    服务器在发送的时候是连续发送的正像hopewoo 说的应该是发生粘包了
    而客户端在接收的时候没有对粘包的情况做处理,很有可能第一次接收的时候就把数据都接收完了
      

  10.   

    另外你说的阻塞是客户端阻塞,服务器可不管你,服务器第一次和第2次发送不会管你客户端是不是阻塞的,而是连续发送了,发送的数据首先保存在客户端的socek缓存里面,用recv实际是从socek缓存中将数据取出
      

  11.   

    这个不是数据量大不大的问题,呵呵.
    粘包并不是和数据量有关的.
    SOCKET client;这个不算流对象,用SYSTEM.IO空间下面的对象.
      

  12.   

    TO:SOCKET client;这个不算流对象,用SYSTEM.IO空间下面的对象.具体是用SYSTEM.IO下面的哪个类哦???能说具体些吗?  谢谢
      

  13.   

        tcp粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。  出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由tcp协议本身造成的,tcp为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常tcp会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据选至这里:http://media.ccidnet.com/media/swm/153/06001.htm
        我这里应该不是粘包的问题,因为我是单步执行都不可以的;我单步执行到客服端第二次recv(第五步)不阻塞,然后再执行服务器第二次发送数据(第四步)的。     看来我是不是需要直接就这样处理了:服务器端只tcpServer->Send一次,这个数据包包括:                 (char *)reqPack + pCom+reqPack->dwoffset(也就是把结构体数据与偏移地址数据一起发送),客服端也只接收一次:iRecv = recv(client, buff, 1024, 0); 
        应该这样要好些吧 请大家指点下,服务器端程序是别人做好了的 这样我就要改他的程序了
      

  14.   

    int check=buff.length;
    while (true){
       check -= iRecv;
       if(check==0){
          // 数据已经全部接收 
         break;
       }else{
          // 数据已经部分接收
         continue;
       }}
     //     这是c#的代码          
      

  15.   

    问题解决了:iRecv = recv(client, buff, sizeof(ReqPack), 0);if (reqPackData->ReqNo == ((ReqPack *)buff)->ReqNo++)
          iRecv = recv(client, buff, ((ReqPack *)buff)->dwSize, 0);这样就可以了 感谢大家