0

考虑以下示例代码:

#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


也许可以这样问这个问题 -作为read返回0EOF原样socketpairSOCK_STREAM我希望EOF一旦从套接字读取所有内容并且另一侧关闭,它将被“命中”。这个对吗?

4

1 回答 1

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.aspx,Graceful Shutdown Server Socket in Linux

编辑 :

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

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

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

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

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

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

于 2014-08-22T13:25:55.997 回答