我有一个父进程和一个分叉子进程,它们共享一个用socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)
创建的Unix域IPC套接字。这两个进程都关闭socket对的一端,并将另一端保存到sock
变量中。之后他们这样做:
int sock; // Unix-domain socket
void child_main()
{
printf("I am child\n");
sleep(1);
close(sock);
}
void parent_main()
{
printf("I am parent\n");
write(sock, "hello", 5);
char buf[100];
int ret = read(sock, buf, 100); // this read will return ECONNRESET
if (ret == -1) {
perror("read");
exit(-1);
}
}
父进程将一些数据写入套接字,而子进程不会读取它。相反,孩子关闭了套接字。现在我关注的是父进程中的read
失败了ECONNRESET(连接由对等重置),而我希望它将返回“0”表示流结束。因为通过调用close
来关闭套接字的另一端正常。
现在,我理解这种行为(在不读取待处理数据的情况下关闭套接字会生成ECONNRESET),但这在哪里记录了? man read
对ECONNRESET一无所知,但它提到:
可能会发生其他错误,具体取决于连接到fd的对象
man page for unix domain sockets只说:
ECONNRESET:意外关闭了远程套接字。
但是由于Unix域套接字是本地IPC的东西,我想它可能会更加具体地说明发生此错误时的情况。
我的“更深层次的想法”是这样的:如果规范说明例如:只有当没有数据要从套接字中读取时,close
才会生成流末尾标记,它如何知道其他进程是否只是要编写一些?这不会造成竞争条件吗?内核如何知道连接是否正常关闭?
答案 0 :(得分:2)
使用有状态套接字(unix domain或tcp),区分“无数据可用”和另一端套接字关闭的最佳方法是首先使用select(),传递readfds(参见man 2 select) )。如果且仅当select指示读取事件时,则尝试在套接字上读取()。如果读取的字节数为0,则表示套接字已关闭(由对等方重置连接)。