在多个客户端请求上,给定的服务器代码应响应每个客户端请求的序号。此外,对于每个客户端请求,服务器应该分叉进程。子进程然后等待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);
}
}
答案 0 :(得分:0)
问题可能是在fork
之后,在父级中你关闭管道的两端,所以无限循环的下一次迭代你尝试使用管道但是它已经关闭了。 / p>
您还应该处理子进程的收获,否则它们将成为僵尸,直到父进程退出。这可以通过为SIGCHLD
和信号处理程序调用{{3}}安装信号处理程序来完成。
答案 1 :(得分:0)
在父进程中,您尝试从空管道读取,read()
将阻塞直到数据可用,因此它会阻塞,直到子进程唤醒并调用write()
。在致电pipe()
,
pipe(fd);
write(fd[1], &num, sizeof(num));
它会解决你的问题。
Joachim Pileborg关于处理儿童过程收获的说法很重要。