如果使用 MSG_PEEK 的非阻塞接收成功,后续不使用 MSG_PEEK 的接收也会成功吗?

发布于 2024-07-19 04:39:45 字数 694 浏览 7 评论 0原文

这是我正在处理的一些代码的简化版本:

void
stuff(int fd)
{
    int ret1, ret2;
    char buffer[32];

    ret1 = recv(fd, buffer, 32, MSG_PEEK | MSG_DONTWAIT);
    
    /* Error handling -- and EAGAIN handling -- would go here.  Bail if
       necessary.  Otherwise, keep going.  */
     
    /* Can this call to recv fail, setting errno to EAGAIN?  */
    ret2 = recv(fd, buffer, ret1, 0);
}

如果我们假设第一次调用 recv 成功,返回 1 到 32 之间的值,那么可以安全地假设第二次调用也会成功吗? ret2 可以小于 ret1 吗? 在哪些情况下?

(为了清楚起见,假设在第二次调用 recv 期间没有其他错误条件:没有传递信号,不会设置 ENOMEM 等。还假设没有其他线程会查看 fd。

我是在 Linux 上,但我相信 MSG_DONTWAIT 是这里唯一特定于 Linux 的东西,假设之前在其他平台上设置了正确的 fnctl。)

Here's a simplified version of some code I'm working on:

void
stuff(int fd)
{
    int ret1, ret2;
    char buffer[32];

    ret1 = recv(fd, buffer, 32, MSG_PEEK | MSG_DONTWAIT);
    
    /* Error handling -- and EAGAIN handling -- would go here.  Bail if
       necessary.  Otherwise, keep going.  */
     
    /* Can this call to recv fail, setting errno to EAGAIN?  */
    ret2 = recv(fd, buffer, ret1, 0);
}

If we assume that the first call to recv succeeds, returning a value between 1 and 32, is it safe to assume that the second call will also succeed? Can ret2 ever be less than ret1? In which cases?

(For clarity's sake, assume that there are no other error conditions during the second call to recv: that no signal is delivered, that it won't set ENOMEM, etc. Also assume that no other threads will look at fd.

I'm on Linux, but MSG_DONTWAIT is, I believe, the only Linux-specific thing here. Assume that the right fnctl was set previously on other platforms.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

当梦初醒 2024-07-26 04:39:45

POSIX 标准对 MSG_PEEK 进行了规定:

数据被视为未读,下一个recv()或类似函数仍将返回该数据

这似乎意味着除非ret2-1,否则它将是相同的作为ret1

The POSIX standard specifies about MSG_PEEK:

the data is treated as unread and the next recv() or similar function will still return this data

That seems to mean that unless ret2 is -1, it will be the same as ret1.

半透明的墙 2024-07-26 04:39:45

您还必须考虑在不同线程上的 ret1 和 ret2 之间可能调用不同的 recv 调用的可能性。 另一个调用将获取您的数据,而 ret2 最终没有数据,或者意外地减少了数据。

如果您的应用程序不是多线程的,或者设计为 fd 仅由这两个调用使用,那么您可以忽略这一点。 但如果这是一个风险,那么您应该将这两个调用放入锁定机制中。

You must also consider the possibility that a different recv call, on a different thread, might be called between ret1 and ret2. That other call would get your data, leaving ret2 to end up with no data, or unexpectedly less data.

If your app isn't multi-threaded, or is designed so that the fd is only used by these two calls, then you can ignore this. But if this is a risk, then you should put the two calls inside a locking mechanism.

绅刃 2024-07-26 04:39:45

我不确定 EAGAIN,但认为 EBADF 或 ECONNRESET 是可能的。

I'm not sure about EAGAIN, but think that EBADF or ECONNRESET are possible.

薄荷梦 2024-07-26 04:39:45

在没有 MSG_PEEK 的情况下第二次调用 recv() 可能会失败并显示 EINTR 或返回不完整的数据,因为它已被信号中断。

Your second call to recv() without MSG_PEEK can fail with EINTR or return incomplete data because it has been interrupted by a signal.

冬天旳寂寞 2024-07-26 04:39:45

对于您的简单情况,后续的 recv 将返回 ret1 字节数(如果 ret1 是不是错误)。 然而,对于多线程设计来说,情况可能并不总是如此。

For your simple case, the subsequent recv will return ret1 number of bytes (if ret1 was not an error). However, for Multi-threaded design, it may not always be true.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文