繁体   English   中英

Unix IPC套接字:关闭一端而不读取它

[英]Unix IPC socket: closing one end without reading from it

我有一个父进程和一个分叉子进程,它们共享一个Unix域IPC套接字,使用socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) 这两个进程都关闭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的对象,可能会发生其他错误

unix域套接字手册页只说:

ECONNRESET:远程套接字意外关闭。

但是由于Unix域套接字是本地IPC的东西,我想它可能会更加具体地说明发生此错误时的情况。

我的“深层思考”是这样的:如果规范说如果没有数据要从套接字中读取,例如close将生成流末尾标记,它如何​​知道其他进程是否不仅仅是写一些? 这不会造成竞争条件吗? 内核如何知道连接是否会正常关闭?

使用有状态套接字(unix domain或tcp),区分“无数据可用”和另一端套接字关闭的最佳方法是首先使用select(),传递readfds(参见man 2 select)。 如果且仅当select指示读取事件时,则尝试在套接字上读取()。 如果读取的字节数为0,则表示套接字已关闭(由对等方重置连接)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM