本来想散200的,不知道怎么散^_^最近CSDN里一下子多了好多完成端口的例子,相信大家也看了不少了,有蛮多很好的贴子的,对大家初步认识,了解完成端口很有帮助。网上也有些现在的类,处理只是对客户发来的消息只是简单的回发,我自己写的完成端口曾经(也许)可以正常运行,但现在不行了,如果我只是对客户发来的消息简单的返回的话,完全没问题。
但我要的不是这样的,一个客户发来的消息,要转发给另一个用户,我现在的问题就是,假设A连发两次消息给B,B第一次能正常收到,第二次发的收不到了,要等到B给A发消息后才能收到。我知道是WSASend & WSARecv没有投递好,我试过好多次,都搞不好,哪位兄弟能帮忙说说。

解决方案 »

  1.   

    方便的话给我代码,我帮你看看
    [email protected]
      

  2.   

    粘包了引用 ljhnew 这是有TCP/IP协议决定的,特别是“报文的分组发送”,当IP层在传输中,不能把所有的数据一次传送出去,就会将数据包分组,所以就会导致出你的问题。这只是一个比较简单的解释,如果你希望了解根详细的环节,可以参考一下具体的TCP/IP协议。如在我们普通的以太网上,如果你一次发送1M的数据,而以太网上规定一次的传输最大数据为1500左右(MTU),此时,你很可能在一次recv调用时并不会得到所有的1M数据,你可以用flags=MSG_WAITALL来实现,不过一次接收1M的数据,对于一般的TCP/IP协议栈来说,比较难以处理,所以,你可以采用循环多次调用(最好是block模式)来得到数据。
    对于发送数据包来说,也是同样道理,如果你一次发送的数据超过了协议栈的缓冲(特别是在单片机嵌入式系统中),那么发送调用就会给你返回一个实际发送出的数据或直接返回失败。
      

  3.   

    HunterForPig(留着口水的猪) :
    代码很长的哦,你有时间看吗?
      

  4.   

    //收到消息后进行处理
    bool CCompletionPort::DealWithMsg(LPCompletionKey lpCompletionKey, LPOverlappedData lpOverlappedData)
    {
    CDealWithMsg dealmsg;
    CHicqMsg*  phicqmsg = NULL; switch(lpOverlappedData->OperationType)
    {
    case IO_Accept:
    return false;
    break; case IO_Write:
    memset(lpOverlappedData->buff, 0, sizeof(lpOverlappedData->buff));
    lpOverlappedData->wsaBuf.buf = lpOverlappedData->buff;
    lpOverlappedData->wsaBuf.len = MAX_PACKET_LEN;
    lpOverlappedData->OperationType = IO_Read;
    break; case IO_Read:
    phicqmsg = (CHicqMsg*)lpOverlappedData->wsaBuf.buf;
    phicqmsg->SetSocket(lpCompletionKey->socket); cout << phicqmsg->GetMsg() << endl; dealmsg.DealWithMsg(phicqmsg, lpOverlappedData);
    break;
    } return true;
    }
    //投下一个IO操作
    bool CCompletionPort::PostNextOperation(LPCompletionKey lpCompletionKey, LPOverlappedData lpOverlappedData)
    {
    switch(lpOverlappedData->OperationType)
    {
    case IO_Accept:
    break; case IO_Write: return SendMsg(lpCompletionKey, lpOverlappedData); break; case IO_Read: return RecvMsg(lpCompletionKey, lpOverlappedData); break; default:
    break;
    } return true;
    }
      

  5.   

    首先你要确认当A发给2个包给B时候,第2个包由A发出后,是服务器收到后没有转给B, 还是B根本没收或者收了没触发? 如果是后者则要在CLIENT找原因。 如果是服务器的原因,那么就要找服务器收到没,服务器如果收到了把消息放到哪里了,为什么会没发出去。。总之,一句话,只有自己慢慢的调试打LOG吧。
      

  6.   

    现在的问题就是,假设A连发两次消息给B,B第一次能正常收到,第二次发的收不到了,要等到B给A发消息后才能收到。
    我知道是WSASend & WSARecv没有投递好,我试过好多次,都搞不好,哪位兄弟能帮忙说说。
    //=====================================================================================
    很明显: 如果A不连续发给B B 能收到,如果A连续发的话,B就不能正确接收了;
     所以肯定是你服务器的程序写的问题,也就是服务器只是收到了第一次的消息,
    然后就没管了,你发的数据肯定不大,所以第一次recv()的时候应该全接收到了两
    次发的数据,但是你抛弃了第二次的数据; 
    这个问题能解决 ,不介意的话可以发代码到我邮箱,我一定能搞好(有过教训)
    [email protected]
      

  7.   

    http://dev.csdn.net/develop/article/40/40554.shtm
    http://dev.csdn.net/develop/article/29/29240.shtm
    http://dev.csdn.net/develop/article/23/23737.shtm
    http://dev.csdn.net/develop/article/15/15211.shtm
    http://www.csdn.net/develop/Read_Article.asp?Id=15212
    http://www.csdn.net/develop/Read_Article.asp?Id=15224
    http://www.csdn.net/develop/Read_Article.asp?Id=15225
    http://www.csdn.net/develop/Read_Article.asp?Id=15226
    http://www.csdn.net/develop/Read_Article.asp?Id=15228
    http://www.csdn.net/develop/Read_Article.asp?Id=16630
    http://www.csdn.net/develop/Read_Article.asp?Id=23504
    http://www.csdn.net/develop/Read_Article.asp?Id=11899
      

  8.   

    我的做法是这样的:
    如果数据连续很快地发送确实有粘包,我采用的方法就是简单地在每个完整数据包的前面加一个长度,我认为服务器端对于不同的socket收发IO操作是无序的,对于同一个socket的recv操作是有序的,将收到的数据放入一个缓冲区,通过读写的互斥来提取完整的数据包。要注意的是只有确定WSARecv完成的情况下才能再次投递。