【问题标题】:Proper closure of a socket - other side gets stuck when reading正确关闭套接字 - 读取时另一侧卡住
【发布时间】:2018-07-13 00:10:35
【问题描述】:
while (((connfd = accept(listenfd)) != -1){
    if (fork() == 0) {
        write(connfd, buffer ,strlen(buffer));
        close(connfd);
    }
}

大家好,我收到了 OS 考试的样题。 假设我有一个使用上述代码处理多个客户端的 TCP 服务器。如问题中所述,其余代码应该是有效的。现在,每次客户端连接到该服务器时,它都会从中读取数据,然后卡住。这个问题的正确答案是因为服务器没有正确关闭与客户端的连接。

我不确定我是否完全明白,不是

关闭(套接字)

够了吗? 就我而言,当一个套接字被一侧关闭时,另一侧读取 EOF 并返回 0。考虑到客户端在读取时卡住了,它不应该到达那个 EOF 并继续前进吗?

【问题讨论】:

    标签: c sockets operating-system


    【解决方案1】:

    fork() 将在子进程中返回 0,在父进程中返回正 pid。因此close(connfd); 只会在子进程中被调用。

    但是,父进程执行了accept,并且它仍然为套接字保存一个打开的文件描述符。它也需要关闭它。在关闭所有打开的文件描述符之前,不会关闭套接字。也就是说,你需要类似的东西

    pid_t child_pid = fork();
    if (child_pid == 0) {
        write(connfd, buffer ,strlen(buffer));
        close(connfd);
    }
    else if (child_pid > 0) {
        // parent
        close(connfd);
    }
    else {
        // a fork error occurred, handle and remember to close(connfd)
    }
    

    【讨论】:

      【解决方案2】:

      对@AnttiHaapala 的回答的补充。

      您不应在发送内容后立即关闭套接字。一旦数据排队,写入就会返回,并且实际上可能在发送所有内容之前发生关闭。

      万无一失的方法是使用graceful shutdown:

      pid_t child_pid = fork();
      if (child_pid == 0) {
          write(connfd, buffer ,strlen(buffer));
          shutdown(connfd, SD_SEND);              // send an EOF condition
          while (read(connfd, buffer, sizeof(buffer) > 0);  // wait for the peer to close its side
          close(connfd);          // and actually close
      }
      else if (child_pid > 0) {
          // parent
          close(connfd);          // direct close because no send is pending
      }
      else {
          // a fork error occurred, handle and remember to close(connfd)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-10
        • 2015-07-30
        • 2018-12-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多