2010-11-05 57 views
0

我的代码开始:的Winsock的recv给10014错误

typedef std::vector<unsigned char> CharBuf; 
static const int RCV_BUF_SIZE = 1024; 
SOCKET m_socket = a connected and working socket; 

// ... 

CharBuf buf; // Declare buffer 
buf.resize(RCV_BUF_SIZE); // resize buffer to 1024 
char* p_buf = reinterpret_cast<char*>(&buf[0]); // change from unsigned char to char 
//char p_buf[RCV_BUF_SIZE]; 

int ret = recv(m_socket, p_buf, RCV_BUF_SIZE, 0); // Does not work 

for (int i=0; i<RCV_BUF_SIZE; ++i) // Works (does not crash, so the buffer is ok) 
    char c = p_buf[i]; 

//... 

现在,当我运行这段代码RET变为-1和WSAGetLastError()返回10014,这意味着指针是坏的。
但我不明白为什么这不应该工作?如果我将reinterpret_cast行注释掉,并使用下面的行,它会起作用!
可能有人认为reinterpret_cast有风险,但我认为应该可以,因为无符号字符和有符号字符的大小完全相同。
就我所知,std :: vectors应该是安全的,可以直接在内存中寻址。

有趣的是,当我在send()中使用相同的向量类型做同样的事情时,它可以工作!发送功能:

void SendData(const CharBuf& buf) 
{ 
    buf.resize(RCV_BUF_SIZE); // resize buffer to 1024 
    const char* p_buf = reinterpret_cast<const char*>(&buf[0]); // change from unsigned char to char 

    int ret = send(m_socket, p_buf, (int)buf.size(), 0); // Works 
} 

正如我们看到的,除了在这种情况下CharBuf是常量没有区别,可以在改变什么?

为什么recv()比send()更敏感? recv()怎么能知道指针是无效的(它显然不是)?它应该看到的只是一个char数组!

根据要求我的整个接收功能(请记住,我在那里不能拼写出每一个功能,但我认为他们应该是相当不言自明。

bool TcpSocket::ReceiveData(CharBuf* pData) 
{ 
    if (!CheckInitialized("ReceiveData")) 
     return false; 


    if (m_status != CONNECTED_STAT) 
    { 
     AddToErrLog("Socket not connected", 1, "ReceiveData"); 
     return false; 
    } 

    int ret; 
    pData->resize(RCV_BUF_SIZE); 
    char* p_buf = reinterpret_cast<char*>(&pData[0]); 

    ret = recv(m_socket, p_buf, RCV_BUF_SIZE, 0); 

    switch (ret) 
    { 
    case 0: // Gracefully closed 
     AddToLog("Connection gracefully closed", 2); 
     Shutdown(); // The connection is closed, no idea to keep running 

     return true; 

    case SOCKET_ERROR: // Error 
     ret = WSAGetLastError(); 
     if (ret == 10004) // This indicates the socket was closed while we were waiting 
      AddToLog("Socket was shut down while waiting for data", 1, "ReceiveData(1)"); 
     else 
      AddToErrLog("Receive data failed with code: " + CStr(ret)); 

     AddToLog("Connection ended with error", 2); 

     Shutdown(); 
     return false; 

    default: // Normal operation 
     pData->resize(ret); // Remove unused space 

     return true; 
    } 
} 

没关系。我发现当我尝试为其他人解释它时,你会发现你的错误:) 我把它留给读者来弄清楚什么是错误的,但我会给& pData [0 ]作为提示。 感谢您的帮助:D

+0

操作系统可以告诉你传递了一个错误的指针,并且可以返回EFAULT而不是简单地杀死你的程序。发布您正在使用的确切代码,或最小的测试用例。你有什么好看的。 – Thanatos 2010-11-05 16:51:55

+0

片段看起来不错。所以......在你正在编译的实际代码中,你是否仔细检查过“buf”实际上是否分配了一个缓冲区?你是否检查过是否意外地调用了'buf.reserve()'而不是'buf.resize()'?你是否检查过'p_buf'的值,看它在传递给'recv'之前是否看起来合理? – TheUndeadFish 2010-11-05 17:12:06

+0

如果你检查整个函数,我相信你会发现我犯的错误,指针可以欺骗你有时:) – DaedalusAlpha 2010-11-05 17:15:40

回答

0

粘贴整个函数时自己找到答案,& pData [0]是一个提示。

+0

是的,这是问题线。对于其他人的参考,'pData'参数是一个CharBuf *指针,因此访问'pData [0]'不会正确调用'std :: vector :: operator []'。您需要先取消引用指针,例如:char * p_buf = reinterpret_cast (&(* pData)[0]);' – 2010-11-06 01:42:52

+0

您也可以使用at()函数:char * p_buf = reinterpret_cast (& (pData->在(0)));这实际上就是我所做的。 – DaedalusAlpha 2010-11-08 08:36:12