从unix本地套接字和缓冲区大小接收

时间:2012-04-11 14:23:52

标签: c++ sockets unix

我遇到了unix本地套接字问题。在读取比我的临时缓冲区大小更长的消息时,请求需要的时间太长(可能无限期)。

经过一些测试后添加: 冻结:: recv仍有问题。当我发送(1023 * 8)字节或更少的字节到UNIX套接字 - 一切正常,但当发送超过(1023 * 9) - 我得冻结recv命令。 可能是FreeBSD默认的UNIX套接字限制或C ++默认套接字设置?谁知道?


我进行了一些附加测试,当我尝试读取消息> =(1023 * 9)字节长时,我100%确定它在执行:: recv命令时在最后9次尝试时“冻结”。 (第8次itterationg进展顺利。)

我在做什么: 我们的想法是从带有

的套接字读取do / while循环
::recv (current_socket, buf, 1024, 0);

并检查buf是否有特殊符号。如果没有找到:

  1. 将缓冲区的内容合并到stringxxx += buf;
  2. bzero temp buf
  3. 继续:: recv循环
  4. 如何解决while循环中请求时间过长的问题?

    有没有更好的方法来清除缓冲区?目前,它是:

     char buf [1025];
     bzero(buf, 1025);
    

    但我知道bzero在新的c ++标准中已被弃用。

    修改 * “为什么需要清理缓冲区 *

    我在这个问题的评论中看到了问题。如果没有缓冲区清理,那么在读取缓冲区的下一个(最后一个)读操作中,它将包含消息第一部分的“尾部”。

    示例:

     // message at the socket is "AAAAAACDE"
     char buf [6];
     ::recv (current_socket, buf, 6, 0); // read 6 symbols, buf = "AAAAAA"
     // no cleanup, read the last part of the message with recv
     ::recv (current_socket, buf, 6, 0); 
     // read 6 symbols, but buffer contain only 3 not readed before symbols, therefore
     // buf now contain "CDEAAA" (not correct, we waiting for CDE only)
    

4 个答案:

答案 0 :(得分:1)

您可以使用

代替bzero,而不是memset(buf, 0, 1025);
{{1}}

答案 1 :(得分:1)

这是两个不同的问题。由于代码中的错误,很长一段时间可能是一些无限循环,与清除缓冲区的方式无关。事实上,您不需要清除缓冲区; receive 返回读取的字节数,因此您可以扫描缓冲区以查找SPECIAL_SYMBOL。

如果您粘贴代码,也许我可以提供帮助。更多。

答案 2 :(得分:1)

只是为了澄清:{C} 11中不推荐bzero。相反,它从未成为任何 C或C ++标准的一部分。 C从20多年前的memset开始。对于C ++,您可以考虑使用std::fill_n代替(或仅使用std::vector,它可以自动进行零填充)。然后,我不确定在这种情况下是否有充分理由将缓冲区置零。

答案 3 :(得分:1)

当你的recv()进入无限循环时,这可能意味着它在迭代中没有取得任何进展(即,你总是得到一个零大小的短读,所以你的循环永远不会退出,因为你没有得到任何数据)。对于流套接字,零大小的recv()表示远程端已断开连接(当输入位于EOF时,它与文件read()类似,也会得到零字节),或者至少它关闭了发送通道(特别是TCP)。

检查您的PHP脚本是否实际发送了您声明发送的数据量。

添加一个小的(非敏感的)示例,以便在循环中正确使用recv():

char buf[1024];
std::string data;
while( data.size() < 10000 ) { // what you wish to receive
    ::ssize_t rcvd = ::recv(fd, buf, sizeof(buf), 0);
    if( rcvd < 0 ) {
        std::cout << "Failed to receive\n";  // Receive failed - something broke, see errno.
        std::abort();
    } else if( !rcvd ) {
        break; // No data to receive, remote end closed connection, so quit.
    } else {
        data.append(buf, rcvd); // Received into buffer, attach to data buffer.
    }
}

if( data.size() < 10000 ) {
    std::cout << "Short receive, sender broken\n";
    std::abort();
}

// Do something with the buffer data.