从管道或套接字对读取一端关闭直到到达 EOF 是否安全? [英] Is it safe to read from pipe OR socketpair with one end closed till reaching EOF?

查看:17
本文介绍了从管道或套接字对读取一端关闭直到到达 EOF 是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下示例代码:

#include <sys/socket.h>

int main()
{
    int sv[ 2 ] = { 0 };
    socketpair( AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, sv );

    for( unsigned ii = 0; ii < 5; ++ii )
    {
        int* msg = new int( 123 );
        if( -1 == send( sv[ 0 ], &msg, sizeof(int*), MSG_NOSIGNAL ) )
        {
            delete msg;
        }
    }

    close( sv[0] );
    sleep( 1 );

    int* msg = 0;
    int r;
    while( ( r = read( sv[ 1 ], &msg, sizeof(int*) ) ) > 0 )
    {
        delete msg;
    }

    return 0;
}

显然,代码运行良好,但这并不意味着它不是 UB.

在手册页中找不到任何内容,这保证了当 sv[ 0 ] 关闭时,read 仍然能够从 read 读取所有内容code>sv[1],由send发送.

Couldn't find anything in the man pages, which guarantees, that when sv[ 0 ] is closed, the read will still be able to read everything from sv[ 1 ], sent by the send.

也许可以这样问这个问题 - as readEOFsocketpair<返回 0/code> 是 SOCK_STREAM,我希望 EOF 将在从套接字读取所有内容并且另一侧关闭后命中".这是正确的吗?

Maybe the question could be asked like this - as read returns 0 for EOF and as the socketpair is SOCK_STREAM, I expect the EOF will be "hit" once everything is read from the socket and the other side is closed. Is this correct?

推荐答案

AFAIK 它可以工作,但闻起来很 UB.

AFAIK it can work, but smells UB.

正确的方法是正常关机:

  • shutdown(s, 1) 或(更好的shutdown(s, SHUT_WR))
  • 在输入时读取直到 eof
  • 然后才调用 close.

(参考:http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547%28v=vs.85%29.aspxLinux 中的正常关闭服务器套接字)

看完R..评论后,不知道是不是有点糊涂了,做了一些测试,又看了一遍文档.而且……我现在认为我所说的适用于一般套接字使用(包括 AF_INET 套接字),但不适用于特殊的 AF_INET 套接字对.

After reading R.. comment, I wondered if I was not a little confused, did some tests and read documentation again. And ... I now think what I said is true for general socket usage (include AF_INET sockets), but not for the special AF_INET socketpair.

我的测试给系统带来了更大的压力,因为我在 FreeBSD 9 系统上发送了 8 个 1024 字节的数据包.我停在那里,因为发送更多会被阻止.在 sv[0] 关闭后,我可以成功读取我的 8 个数据包.

My test was put a little more stress on the system, since I send 8 packets of 1024 bytes on a FreeBSD 9 system. I stopped there because sending more would have blocked. And after the close on sv[0] I could successfully read my 8 packets.

所以它适用于不同的内核,但除了 AF_UNIX 套接字不支持 OOB 数据之外,找不到有效的参考.

So it works on different kernels, but could not find a valid reference for it except that AF_UNIX sockets do not support OOB data.

我也可以确认使用关机,工作正常.

I could also confirm that using shutdown, works fine.

结论:就我而言,我会坚持优雅关闭来关闭套接字,但主要是因为我不想考虑底层协议.

Conclusion : As far as I am concerned, I would stick to graceful shutdown for closing a socket, but mostly because I do not want to think about the underlying protocol.

希望有更多知识的人能给一份参考文档

Hope somebody else with more knowledge could give a piece of reference documentation

这篇关于从管道或套接字对读取一端关闭直到到达 EOF 是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆