从一端封闭直到达到EOF的管道或插座读取是否安全?

时间:2014-08-22 12:23:29

标签: c++ c linux unix socketpair

考虑以下示例代码:

#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仍然可以读取sv[ 1 ]发送的所有内容。 send


也许可以这样问这个问题 - read0返回EOFsocketpairSOCK_STREAM,我期待EOF将被&#34;点击&#34;一旦从插座读取所有内容,另一侧关闭。这是对的吗?

1 个答案:

答案 0 :(得分:0)

AFAIK它可以工作,但闻起来有UB。

正确的方法是正常关闭

  • shutdown(s, 1)或(更好shutdown(s, SHUT_WR)
  • 读到输入时的eof
  • 然后再致电。

(参考文献:http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547%28v=vs.85%29.aspxGraceful Shutdown Server Socket in Linux

编辑:

阅读R ..评论后,我想知道我是不是有点困惑,做了一些测试并再次阅读文档。而且......我现在认为我所说的是普通套接字使用(包括AF_INET套接字),但不适用于特殊的AF_INET套接字。

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

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

我还可以确认使用关机,工作正常。

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

希望有更多知识的人可以提供一份参考文档