0

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

经过一些测试后添加: 在 ::recv 处冻结仍然存在问题。当我向 UNIX 套接字发送 (1023*8) 字节或更少时 - 一切正常,但是当发送超过 (1023*9) 时 - 我在 recv 命令上冻结。 也许它的 FreeBSD 默认 UNIX 套接字限制或 C++ 默认套接字设置?谁知道?


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

我在做什么: 这个想法是从一个套接字读取一个 do/while 循环

::recv (current_socket, buf, 1024, 0);

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

  1. 将缓冲区的内容合并到stringxxx += buf;
  2. bzero 温度缓冲区
  3. 继续 ::recv 循环

如何解决请求在 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

4 回答 4

1

而不是bzero,您可以使用

memset(buf, 0, 1025);
于 2012-04-11T14:25:55.847 回答
1

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

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

于 2012-04-11T14:30:30.090 回答
1

只是为了澄清:bzero在 C++ 11 中不被弃用。相反,它从未成为任何C 或 C++ 标准的一部分。C 始于memset20 多年前。对于 C++,您可能会考虑使用std::fill_n代替(或仅使用std::vector,它可以自动填零)。再说一次,我不确定在这种情况下是否有充分的理由对缓冲区进行零填充。

于 2012-04-11T14:41:03.010 回答
1

当您recv()进入无限循环时,这可能意味着它在迭代上没有任何进展(即,您总是立即获得零大小的短读,因此您的循环永远不会退出,因为您没有获得任何数据)。对于流套接字,大小为零的 a意味着远程端已断开连接(当输入位于 EOF 时,recv()它类似于从文件中获取零字节),或者至少它已关闭发送通道(即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.
于 2012-04-11T20:00:01.747 回答