【问题标题】:Unix socket gets stuck at accept()Unix套接字卡在accept()
【发布时间】:2021-02-17 04:03:04
【问题描述】:

我正在编写一个应该等待客户端连接的服务器。访问主循环服务器后应该“反弹”这么久accept() 确实返回一个不同的值然后 -1。问题是accept() 方法阻塞了执行而不是返回任何值。如果没有引发无效参数标志,这可能是什么原因?

Bellow 是我的代码的最小可重现示例:

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/unistd.h> // unlink

#define MAX_LISTCLI 5

int main(void) {
  uint server_id, len;
  struct sockaddr_un server;

  if ((server_id = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    perror("Socket");
    exit(1);
  }
  server.sun_family = AF_UNIX;
  strcpy(server.sun_path, "free_socket");
  if (unlink(server.sun_path) != -1)
    fprintf(stderr, "Server was NOT aboard correctly?\n");
  len = (strlen(server.sun_path) + sizeof(server.sun_family));
  if (bind(server_id, (struct sockaddr *)&server, len) == -1) {
    perror("Bind");
    exit(1);
  }
  if (listen(server_id, MAX_LISTCLI) == -1) {
    perror("Listen");
    exit(1);
  }
  _Bool done = 0;
  while (!done) {
    uint remote_id;
    struct sockaddr_un remote;

    len = sizeof(remote);
    // Bounce if connection was not obtained and wait for the client to connect
    printf("Connecting..\n");
    if ((remote_id =
         accept(server_id,
                (struct sockaddr *)&remote ,&len)) == -1) {
      fprintf(stderr, "Bounce..\n");
      continue;
    }
    fprintf(stderr, "Connected.\n");
    // Replay to the user..
    done = 1;
  }
  close(remote_id);
  close(server_id);
  unlink(server.sun_path);
  return 0; 
}

【问题讨论】:

  • accept() 上阻塞并没有错,这就是“等待传入连接”的意义所在。我注意到您的代码是一个最小的示例,但是,除非您的程序在等待连接时需要做其他事情,否则您应该将其保留为阻塞操作。
  • 贴出的代码无法编译!如果您发布无法编译的代码,您希望我们如何重现该问题?

标签: c server unix-socket


【解决方案1】:

这里的问题是 server_id 的套接字被阻塞 (refer here)。

如果队列中没有挂起的连接,并且 套接字未标记为非阻塞,accept() 阻塞调用者 直到存在连接。如果套接字被标记 队列中不存在非阻塞且没有挂起的连接, accept() 失败并返回 EAGAIN 或 EWOULDBLOCK 错误。

如果您希望接受调用立即返回,则必须使套接字非阻塞。

编辑:我不建议将其设为非阻塞调用,因为重复执行 while 循环只会浪费 CPU 周期。处理这个问题的理想方法是阻塞接受调用,然后使用fork 系统调用来生成一个新进程。

【讨论】:

  • 这就是我在实际应用程序中所做的,这只是一个简单的最小示例。
  • 或者当它被阻塞时它仍然会接受连接?我不需要在那儿弹跳吗?
  • 所有传入服务器(来自客户端)的连接都附加到队列中,当队列中有一些连接需要满足时,接受调用将立即返回服务器端的套接字文件描述符.但是,如果没有连接请求,则调用将阻塞,直到您获得连接,然后发布它会返回。
  • 谢谢,这是一个有用的信息。但在我的情况下,我需要继续循环,以便服务器可以检查done 标志,它是while 的参数。我在我的真实应用程序中这个标志是一个在接口中使用的指针。
【解决方案2】:

正如在其他帖子中提到的,您需要使您的服务器套接字成为非阻塞的。您可以使用fcntl 来做到这一点。

fcntl(server_id, F_SETFL, O_NONBLOCK);

然后所有通常会阻塞您的套接字的调用都将返回一个标志。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    相关资源
    最近更新 更多