[英]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.