套接字Recv api返回意外值
问题描述:
这个客户端code.server连续发送数据。在这里我正在偷看13(Header Length)字节的消息,获取消息本身编码的数据的大小并创建缓冲区大小为MESSAGE_HEADER_LENGTH +数据长度。套接字Recv api返回意外值
获取总邮件大小后,我正在使用第二个recv从套接字读取数据。 在服务器到客户端之间的初始连接建立和交换hello消息时,它工作正常,但是当服务器发送连续流时说(当我们在客户端服务器上挂断按钮发送固定长度为5000ms的连续消息时)recv工作不正常并且recv缓冲区接收到以垃圾或一段时间为空的字符串之前的原始消息。
#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;
}
}
}
}
}
}
}
答
您的代码有几个问题:
- 你知道
delete[]
是NOP传递空指针? - 为什么在第一次检查
pRecvBuffer
是空指针,你最终得到一个return 0
和在(可怕的)catch(...)
你不? - 你是否知道,捕捉一切与
catch(...)
是一个一般的可怕的想法,特别是如果你不rethrow?有平台(MS)与catch(...)
你甚至陷阱段错误。在您的程序中发现段错误后,您认为安全吗?
无论如何,我认为你观察到的问题的根源是在该行
if(nRecvRetVal > 0)
的原因是,你只是检查,你居然也能看懂一些字节,但你不检查您实际收到的字节数(recv
返回读取的字节数,可能小于调用中指定的数量)。 将结果缓冲区传递给处理函数时,您实际上可能会处理随机存储器,就好像它已从网络中收到一样。
您也可能会发现尝试使用像wireshark这样的工具可以真正检查您的程序从网络接收的数据包。
这是逻辑错误。现在它工作正常 – 2011-03-11 08:15:30