简体   繁体   English

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

[英]receive from unix local socket and buffer size

I'm having a problem with unix local sockets. 我在使用Unix本地套接字时遇到问题。 While reading a message that's longer than my temp buffer size, the request takes too long (maybe indefinitely). 在读取长度超过我的临时缓冲区大小的消息时,请求花费的时间太长(可能无限期)。

Added after some tests: there is still problem with freeze at ::recv. 经过一些测试后添加 ::: recv处的冻结仍然存在问题。 when I send (1023*8) bytes or less to the UNIX socket - all ok, but when sended more than (1023*9) - i get freeze on recv command. 当我向UNIX套接字发送(1023 * 8)个字节或更少的字节时-一切正常,但是当发送大于(1023 * 9)个字节时-我在recv命令中冻结。 maybe its FreeBSD default UNIX socket limit or C++ default socket settings? 也许它的FreeBSD默认UNIX套接字限制或C ++默认套接字设置? Who know? 谁知道?


i made some additational tests and I am 100% sure that its "freeze" on the last 9th itteration when executing ::recv command, when trying to read message >= (1023*9) bytes long. 我进行了一些附加测试,当尝试读取长度大于等于(1023 * 9)字节的消息时,我100%确信在执行:: recv命令时,它在最后第9次“冻结”。 (first 8th itterationg going well.) (第8次发送信号良好)。

What I'm doing: The idea is to read in a do/while loop from a socket with 我在做什么:的想法是从一个套接字读取do / while循环

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

and check buf for a SPECIAL SYMBOL. 并检查buf是否有特殊符号。 If not found: 如果找不到:

  1. merge content of buffer to stringxxx += buf; 将缓冲区的内容合并到stringxxx += buf;
  2. bzero temp buf bzero临时buf
  3. continue the ::recv loop 继续:: recv循环

How do I fix the issue with the request taking too long in the while loop? 如何解决while循环中的请求时间过长的问题?

Is there a better way to clear the buffer? 有更好的方法清除缓冲区吗? Currently, it's: 当前是:

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

But I know bzero is deprecated in the new c++ standard. 但是我知道在新的c ++标准中不赞成使用bzero。

EDIT: * "Why need to clean the buffer * 编辑: * “为什么需要清理缓冲区 *

I see questions at comments with this question. 我在有关此问题的评论中看到了问题。 Without buffer cleanup on the next(last) itteration of reading to the buffer, it will contain the "tail" of first part of the message. 如果不对下一次(最后一次)读取缓冲区进行缓冲区清除,它将包含消息第一部分的“尾部”。

Example: 例:

 // 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)

除了bzero ,您可以使用

memset(buf, 0, 1025);

These are 2 separate issues. 这些是2个独立的问题。 The long time is probably some infinite loop due to a bug in your code and has nothing to do with the way you clear your buffer. 时间长了可能是由于代码中的错误导致的无限循环,与清除缓冲区的方式无关。 As a matter of fact you shouldn't need to clear the buffer; 事实上,您不必清除缓冲区; receive returns the number of bytes read, so you can scan the buffer for your SPECIAL_SYMBOL up to that point. receive返回读取的字节数,因此您可以在此之前扫描缓冲区中的SPECIAL_SYMBOL。

If you paste the code maybe I can help. 如果您粘贴代码,也许我可以帮助您。 more. 更多。

Just to clarify: bzero is not deprecated in C++ 11. Rather, it's never been part of any C or C++ standard. 需要澄清的是: bzero在C ++ 11中并未被弃用。相反,它从未成为任何 C或C ++标准的一部分。 C started out with memset 20+ years ago. C始于20年前的memset For C++, you might consider using std::fill_n instead (or just using std::vector , which can zero-fill automatically). 对于C ++,您可以考虑使用std::fill_n代替(或仅使用std::vector ,它可以自动零填充)。 Then again, I'm not sure there's a good reason to zero-fill the buffer in this case at all. 再说一次,我不确定在这种情况下是否有充分理由将缓冲区零填充。

When your recv() enters an infinite loop, this probably means that it's not making any progress whatsoever on the iterations (ie, you're always getting a short read of zero size immediately, so your loop never exits, because you're not getting any data). 当您的recv()进入无限循环时,这可能意味着它在迭代上没有任何进展(即,您始终会立即读取零大小的简短内容,因此您的循环永远不会退出,因为您没有获取任何数据)。 For stream sockets, a recv() of zero size means that the remote end has disconnected (it's something like read() ing from a file when the input is positioned at EOF also gets you zero bytes), or at least that it has shut down the sending channel (that's for TCP specifically). 对于流套接字,大小为recv()的零表示远程端已断开连接(这类似于将输入置于EOF时也从文件read()也会使您得到零字节),或者至少它已关闭向下发送通道(专门用于TCP)。

Check whether your PHP script is actually sending the amount of data you claim it sends. 检查您的PHP脚本是否实际发送了声称已发送的数据量。

To add a small (non-sensical) example for properly using recv() in a loop: 要添加一个小的(荒谬的)示例以在循环中正确使用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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM