考虑以下示例代码:
#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
为0
返回EOF
而socketpair
为SOCK_STREAM
,我期待EOF
将被&#34;点击&#34;一旦从插座读取所有内容,另一侧关闭。这是对的吗?
答案 0 :(得分:0)
AFAIK它可以工作,但闻起来有UB。
正确的方法是正常关闭:
shutdown(s, 1)
或(更好shutdown(s, SHUT_WR)
)(参考文献: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数据外,找不到它的有效引用。
我还可以确认使用关机,工作正常。
结论: 就我而言,我会坚持优雅关闭以关闭套接字,但主要是因为我不想考虑底层协议。
希望有更多知识的人可以提供一份参考文档