多客户端套接字编程僵尸进程
Multi-client socket programming zombie processes
我希望使用 fork()
系统调用实现与服务器的多客户端连接以传输一些数据。使用命令 ps -a
。我发现在我的客户端程序终止后,在服务器中创建的用于处理数据传输的子进程变成了僵尸进程(对进程显示<defunct>
)。我知道父进程中的 wait()
可能会解决问题,但我需要父进程中的 while 循环 运行 不断接受传入的客户端连接并且不能等待子进程结尾。请帮助我解决僵尸进程问题。我的服务器程序如下:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include<string.h>
int main()
{
int sock = 0;
struct sockaddr_in addr;
int addrlen = sizeof(addr);
char buffer[1024] = {0};
sock = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family=AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(2222);
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
listen(sock,5);
while(1)
{
int conn = accept(sock, (struct sockaddr *)&addr, (socklen_t *)&addrlen);
int pid = fork();
if(pid==0)
{
char buffer[1024] = {0};
int readval = read(conn, buffer, 1024);
printf("%s\n",buffer);
break;
}
else if(pid < 0) printf("Process creation error");
}
close(conn);
close(sock);
return 0;
}
我的客户端程序如下:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
int sock = 0;
struct sockaddr_in saddr;
char msg[] = "Hello Server, this is Client 1";
sock = socket(AF_INET, SOCK_STREAM, 0);
saddr.sin_family=AF_INET;
saddr.sin_port = htons(2222);
connect(sock, (struct sockaddr *)&saddr, sizeof(saddr));
send(sock, msg, strlen(msg), 0);
sleep(20);
close(sock);
return 0;
}
和
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
int sock = 0;
struct sockaddr_in saddr;
char msg[] = "Hello Server, this is Client 2";
sock = socket(AF_INET, SOCK_STREAM, 0);
saddr.sin_family=AF_INET;
saddr.sin_port = htons(2222);
connect(sock, (struct sockaddr *)&saddr, sizeof(saddr));
send(sock, msg, strlen(msg), 0);
sleep(20);
close(sock);
return 0;
}
有两种常见的避免僵尸的方法:
1) 在主循环中使用非阻塞等待,例如 waitpid(-1, ..., WNOHANG)
或
2) 安装 SIGCHLD 处理程序。它是在 child 退出时异步调用的,因此只需等待即可。您甚至不必编写自己的处理程序,因为只需执行 signal(SIGCHLD, SIG_IGN) 就应该 auto-reap 僵尸。请注意,如果您这样做,wait*() 函数将无法为您提供退出代码。
我希望使用 fork()
系统调用实现与服务器的多客户端连接以传输一些数据。使用命令 ps -a
。我发现在我的客户端程序终止后,在服务器中创建的用于处理数据传输的子进程变成了僵尸进程(对进程显示<defunct>
)。我知道父进程中的 wait()
可能会解决问题,但我需要父进程中的 while 循环 运行 不断接受传入的客户端连接并且不能等待子进程结尾。请帮助我解决僵尸进程问题。我的服务器程序如下:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include<string.h>
int main()
{
int sock = 0;
struct sockaddr_in addr;
int addrlen = sizeof(addr);
char buffer[1024] = {0};
sock = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family=AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(2222);
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
listen(sock,5);
while(1)
{
int conn = accept(sock, (struct sockaddr *)&addr, (socklen_t *)&addrlen);
int pid = fork();
if(pid==0)
{
char buffer[1024] = {0};
int readval = read(conn, buffer, 1024);
printf("%s\n",buffer);
break;
}
else if(pid < 0) printf("Process creation error");
}
close(conn);
close(sock);
return 0;
}
我的客户端程序如下:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
int sock = 0;
struct sockaddr_in saddr;
char msg[] = "Hello Server, this is Client 1";
sock = socket(AF_INET, SOCK_STREAM, 0);
saddr.sin_family=AF_INET;
saddr.sin_port = htons(2222);
connect(sock, (struct sockaddr *)&saddr, sizeof(saddr));
send(sock, msg, strlen(msg), 0);
sleep(20);
close(sock);
return 0;
}
和
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
int sock = 0;
struct sockaddr_in saddr;
char msg[] = "Hello Server, this is Client 2";
sock = socket(AF_INET, SOCK_STREAM, 0);
saddr.sin_family=AF_INET;
saddr.sin_port = htons(2222);
connect(sock, (struct sockaddr *)&saddr, sizeof(saddr));
send(sock, msg, strlen(msg), 0);
sleep(20);
close(sock);
return 0;
}
有两种常见的避免僵尸的方法:
1) 在主循环中使用非阻塞等待,例如 waitpid(-1, ..., WNOHANG)
或
2) 安装 SIGCHLD 处理程序。它是在 child 退出时异步调用的,因此只需等待即可。您甚至不必编写自己的处理程序,因为只需执行 signal(SIGCHLD, SIG_IGN) 就应该 auto-reap 僵尸。请注意,如果您这样做,wait*() 函数将无法为您提供退出代码。