【发布时间】:2012-04-23 20:58:28
【问题描述】:
我遇到了 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 是否有特殊符号。如果没有找到:
- 合并缓冲区内容到
stringxxx += buf; - bzero temp buf
- 继续 ::recv 循环
如何解决请求在 while 循环中耗时过长的问题?
有没有更好的方法来清除缓冲区?目前是:
char buf [1025];
bzero(buf, 1025);
但我知道 bzero 在新的 c++ 标准中已被弃用。
编辑: *"为什么需要清理缓冲区*
我在 cmets 看到有这个问题的问题。如果在下一次(最后一次)读取缓冲区时不清理缓冲区,它将包含消息第一部分的“尾部”。
例子:
// 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)
【问题讨论】:
-
为什么一定要清空缓冲区?
-
你会从
recv()的返回值中知道复制了多少字节。我不知道为什么你需要一个特殊字符来知道你已经超过了缓冲区长度。 -
套接字是否以非阻塞模式打开?请参阅
fcntl()的手册页。 -
Martin,回答第一条消息的“编辑”部分。 .
-
chrisaycock,因为缓冲区大小可以小于消息的大小。 (在我的示例中,它不再读取缓冲区大小,受 ::recv 的第 3 个参数限制)