socket Recv api返回意外值

时间:2011-03-11 06:22:12

标签: c++ tcp tcpclient

这个客户端code.server连续发送数据。这里我正在查看13(Header Length)字节消息,获取在消息本身中编码的数据大小,并创建MESSAGE_HEADER_LENGTH + DATA-LENGTH的缓冲区大小。

获取总消息大小后,我使用第二个recv从套接字读取数据。 在初始连接设置和服务器到客户端之间交换hello消息时,它工作正常但是当服务器发送连续流时说(当我们在客户端服务器上的clieck按钮发送具有5000ms间隙的固定长度的连续消息时)recv无法正常工作recv buffer接收原始消息,前面是垃圾或一些空字符串。

#define MESSAGE_HEADER_LENGTH 13

...

while {
    nSelectRetVal = select(NULL, &fdRead,NULL, &fdExcept, &tv);
    if(nSelectRetVal > 0) {
        if(FD_ISSET(pControlMgr->GetConnectionMgr()->GetUDPSocket(),
                    &fdRead)) {
            try {
                char chHeaderBuffer[MESSAGE_HEADER_LENGTH + 1];
                memset(chHeaderBuffer,0,MESSAGE_HEADER_LENGTH + 1);
                int nMsgPeek = recv(pControlMgr->GetConnectionMgr()->GetUDPSocket(),
                                    chHeaderBuffer, MESSAGE_HEADER_LENGTH, MSG_PEEK);
                chHeaderBuffer[MESSAGE_HEADER_LENGTH] = '\0';
                if(nMsgPeek == SOCKET_ERROR)
                    return 0;
                CProtocolMgr objProtocolMgr;
                int Bufferlength = objProtocolMgr.ProtocolMsgSize(chHeaderBuffer) + MESSAGE_HEADER_LENGTH;
                pRecvBuffer = new char[Bufferlength];
                memset(pRecvBuffer, 0, Bufferlength);
                int nRecvRetVal = recv(pControlMgr->GetConnectionMgr()->GetUDPSocket(),
                                       pRecvBuffer, Bufferlength, 0);
                if(nRecvRetVal > 0) {
                    if(pControlMgr->HandlePacket(pRecvBuffer,
                                                 pControlMgr->GetConnectionMgr()->GetServerAddress()) == -1) {
                        if(NULL != pRecvBuffer) {
                            delete [] pRecvBuffer;
                            pRecvBuffer = NULL;
                            return 0 ;
                        }
                    } catch(...) {
                        if(NULL != pRecvBuffer) {
                            delete [] pRecvBuffer;
                            pRecvBuffer = NULL;
                        }
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您的代码存在一些问题:

  1. 您是否知道delete[]在传递空指针时是NOP?
  2. 为什么在第一次检查时pRecvBuffer是空指针,最后是return 0,而(可怕的)catch(...)则不是?
  3. 你是否知道用catch(...)抓住所有内容一般都是一个可怕的想法,特别是如果你不重新抛出?有平台(MS),catch(...)甚至可以捕获段错误。你认为在你的程序中遇到段错之后你觉得安全吗?
  4. 无论如何,我认为您观察到的问题的根源在于

    if(nRecvRetVal > 0)
    

    原因是您只是检查实际上是否能够读取一些字节,但是您没有检查实际接收的字节数(recv返回的读取字节数可能小于呼叫中指定的号码)。 将结果缓冲区传递给处理函数时,实际上可能会处理随机存储器,就像从网络接收到它一样。

    您也可以尝试使用wireshark之类的工具来实际查看您的程序从网络接收的数据包。