我遇到了unix本地套接字问题。在读取比我的临时缓冲区大小更长的消息时,请求需要的时间太长(可能无限期)。
经过一些测试后添加: 冻结:: recv仍有问题。当我发送(1023 * 8)字节或更少的字节到UNIX套接字 - 一切正常,但当发送超过(1023 * 9) - 我得冻结recv命令。 可能是FreeBSD默认的UNIX套接字限制或C ++默认套接字设置?谁知道?
我在做什么: 我们的想法是从带有
的套接字读取do / while循环::recv (current_socket, buf, 1024, 0);
并检查buf
是否有特殊符号。如果没有找到:
stringxxx += buf;
如何解决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)
答案 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.