Unix 套接字卡在 accept()
Unix socket gets stuck at accept()
我正在编写一个应该等待客户端连接的服务器。访问主循环服务器后应该“反弹”这么久 accept()
做 return 一个不同的值然后 -1。问题是 accept()
方法正在阻止执行而不是 returning 任何值。如果没有引发无效参数标志,这可能是什么原因?
波纹管是我的代码的最小可重现示例:
#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;
}
这里的问题是套接字被 server_id 阻塞 (refer here)。
If no pending connections are present on the queue, and the
socket is not marked as nonblocking, accept() blocks the caller
until a connection is present. If the socket is marked
nonblocking and no pending connections are present on the queue,
accept() fails with the error EAGAIN or EWOULDBLOCK.
如果您想立即接受对 return 的调用,您必须使套接字成为非阻塞。
编辑:我不建议将其设为非阻塞调用,因为那样会因为重复执行 while 循环而浪费 CPU 个周期。处理这个问题的理想方法是阻塞 accept 调用,然后使用 fork 系统调用来生成一个新进程。
如其他 post 所述,您需要使您的服务器套接字成为非阻塞的。您可以使用 fcntl.
来做到这一点
fcntl(server_id, F_SETFL, O_NONBLOCK);
然后所有通常会阻塞您的套接字的调用都会 return 一个标志。
我正在编写一个应该等待客户端连接的服务器。访问主循环服务器后应该“反弹”这么久 accept()
做 return 一个不同的值然后 -1。问题是 accept()
方法正在阻止执行而不是 returning 任何值。如果没有引发无效参数标志,这可能是什么原因?
波纹管是我的代码的最小可重现示例:
#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;
}
这里的问题是套接字被 server_id 阻塞 (refer here)。
If no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present. If the socket is marked nonblocking and no pending connections are present on the queue, accept() fails with the error EAGAIN or EWOULDBLOCK.
如果您想立即接受对 return 的调用,您必须使套接字成为非阻塞。
编辑:我不建议将其设为非阻塞调用,因为那样会因为重复执行 while 循环而浪费 CPU 个周期。处理这个问题的理想方法是阻塞 accept 调用,然后使用 fork 系统调用来生成一个新进程。
如其他 post 所述,您需要使您的服务器套接字成为非阻塞的。您可以使用 fcntl.
来做到这一点fcntl(server_id, F_SETFL, O_NONBLOCK);
然后所有通常会阻塞您的套接字的调用都会 return 一个标志。