正如我目前所做的那样this project仅在 C 中,直到此时我才将我的网络服务器用作单线程应用程序。但是,我不想那样了!所以我有以下代码来处理我的工作。
void BeginListen()
{
CreateSocket();
BindSocket();
ListenOnSocket();
while ( 1 )
{
ProcessConnections();
}
}
现在我在 ProcessConnection();
开始之前添加了 fork();
这有助于我允许多个连接!但是,当我添加用于守护应用程序的代码时,在 this answer 中找到.我遇到了一个小问题,使用 fork()
会创建我的整个运行应用程序的副本,这就是 fork()
的目的。所以,我想解决这个问题。
我的 ProcessConnection()
看起来像这样
void ProcessConnections()
{
fork();
addr_size = sizeof(connector);
connecting_socket = accept(current_socket, (struct sockaddr *)&connector, &addr_size);
if ( connecting_socket < 0 )
{
perror("Accepting sockets");
exit(-1);
}
HandleCurrentConnection(connecting_socket);
DisposeCurrentConnection();
}
我该怎么做才能简单地在 connecting=socket = accept
... 之上或之后添加几行,以使其同时接受多个连接?我可以使用 fork();
但是当它归结为 DisposeCurrentConnection();
我想终止该进程并让父线程运行。
最佳答案
我不是 100% 确定你想做什么,买下我的头顶,我更愿意在接受后做 fork ,然后简单地退出()当你'重做。但请记住,当子进程退出时,您需要对 SIGCHLD 信号作出 react ,否则您将有大量的僵尸进程徘徊,等待将它们的退出状态传递给父进程。 C 伪代码:
for (;;) {
connecting_socket = accept(server_socket);
if (connecting_socket < 0)
{
if (errno == EINTR)
continue;
else
{
// handle error
break;
}
}
if (! (child_pid = fork ()))
{
// child process, do work with connecting socket
exit (0);
}
else if (child_pid > 0)
{
// parent process, keep track of child_pid if necessary.
}
else
{
// fork failed, unable to service request, send 503 or equivalent.
}
}
child_pid 需要(如前所述)来终止子进程,但如果您希望使用 waitpid 来收集退出状态也是如此。
关于僵尸进程,如果你对进程发生的事情不感兴趣,你可以为 SIGCHLD 安装一个信号处理程序,然后用 -1 循环 waitpid 直到它没有更多的子进程,就像这样
while (-1 != waitpid (-1, NULL, WNOHANG))
/* no loop body */ ;
waitpid 函数将返回退出的子进程的 pid,因此如果您愿意,可以将此与有关连接的其他一些信息相关联(如果您确实跟踪了 pid)。请记住,如果捕获到 SIGCHLD,accept 可能会在 errno 设置为 EINTR 时退出,没有有效连接,因此请记住在 accept 返回时检查这一点。
编辑:
不要忘记检查错误条件,即 fork 返回 -1。
关于转换为多线程套接字应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/433461/