[英]pipe(), fork(), and sleep()
在多个客户端请求上,给定的服务器代码应为每个客户端请求响应一个顺序号。 同样,对于每个客户端请求,服务器也应该派生一个进程。 然后,子进程等待5秒钟,并减少客户端请求计数。 所以基本上它是一个令牌系统。
代码中的问题是,当我发送多个客户端请求(第一个请求除外)时,其他人被阻止了5秒钟,这是我不想要的。
static int num = 0;
int main(int ac, char *av[]){
struct sockaddr_in saddr;
struct hostent *hp;
char hostname[HOSTLEN];
int sock_id, sock_fd;
FILE *sock_fp;
int pid, fd[2];
pipe(fd);
sock_id = socket(PF_INET, SOCK_STREAM, 0);
if(sock_id == -1)
oops("Socket");
bzero((void *)&saddr, sizeof(saddr));
gethostname(hostname, HOSTLEN);
hp = gethostbyname(hostname);
bcopy((void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length);
saddr.sin_port = htons(PORTNUM);
saddr.sin_family = AF_INET;
if(bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0)
oops("bind");
if(listen(sock_id, 5) != 0)
oops("listen");
while(1) {
sock_fd = accept(sock_id, NULL, NULL);
printf("got a call\n");
if(sock_fd == -1)
oops("accept");
num++;
sock_fp = fdopen(sock_fd, "w");
if(sock_fp == NULL)
oops("fdopen");
fprintf(sock_fp, "Your token number is: %d\n", num);
fclose(sock_fp);
pid = fork();
if(pid == 0){
close(sock_id);
sleep(5);
num--;
close(fd[0]);
write(fd[1], &num, sizeof(num));
printf("Sent: %d\n", num);
close(fd[1]);
exit(0);
}
else if(pid > 0){
close(fd[1]);
read(fd[0], &num, sizeof(num));
printf("Received %d\n", num);
close(fd[0]);
close(sock_fd);
}
}
问题可能是在fork
,在父级中关闭了管道的两端,因此在无限循环的下一次迭代中,您尝试使用管道,但管道已经关闭。
您还应该处理收割子进程,否则它们将变成僵尸,直到父进程退出。 这可以通过为SIGCHLD
安装信号处理程序并在信号处理程序调用wait
。
在父进程中,您尝试从一个空管道中read()
, read()
将阻塞直到有可用数据为止,因此它将阻塞直到子进程唤醒并调用write()
为止。 调用pipe()
之后,向管道中写入一些内容,
pipe(fd);
write(fd[1], &num, sizeof(num));
它会解决您的问题。
约阿希姆·皮勒伯格(Joachim PIleborg)关于处理子进程的收获的观点很重要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.