我在第5章学习Unix网络编程,等待和waitpid功能。我测试功能等待。我首先运行服务器应用程序然后运行客户端(重复几次./a.out)。但服务器只能接受一次请求并终止。 Errno是4岁。
/* server.c
*
* gcc server.c -o server
* ./server & (run in background)
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <signal.h>
void sig_chld(int signum) // SIGCHLD handler
{
int stat;
pid_t pid;
pid = wait(&stat);
}
int main(void)
{
int listenfd;
int connfd;
struct sigaction act;
struct sockaddr_in addr;
socklen_t addrlen;
pid_t pid;
act.sa_handler = sig_chld; // register SIGCHLD handler
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGCHLD, &act, NULL);
addrlen = sizeof(addr);
bzero(&addr, addrlen); // fill server address
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
inet_pton(AF_INET, "192.168.0.10", &addr.sin_addr.s_addr);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bind(listenfd, (struct sockaddr *)&addr, addrlen);
listen(listenfd, 5);
while (1) { // waiting for client request
connfd = accept(listenfd, (struct sockaddr *)&addr, &addrlen);
if (connfd < 0) {
printf("connect\n");
break;
}
pid = fork();
if (pid < 0) {
exit(-1);
} else if (pid == 0) { // child
close(listenfd);
write(connfd, "hello\n", 7);
exit(0);
}
else { // parent
close(connfd);
}
}
return 0;
}
/* client.c
*
* gcc client.c
* ./a.out (repeat several times)
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <errno.h>
#define MAXLINE 4096
int main(void)
{
char buf[1024];
int cliefd;
struct sockaddr_in servaddr;
socklen_t addrlen;
addrlen = sizeof(servaddr);
bzero(&servaddr, addrlen); // fill server address
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(8080);
inet_pton(AF_INET, "192.168.0.10", &servaddr.sin_addr.s_addr);
cliefd = socket(AF_INET, SOCK_STREAM, 0);
if (connect(cliefd, (struct sockaddr *)&servaddr, addrlen) < 0) {
printf("error: %d\n", errno);
exit(-1);
}
read(cliefd, buf, MAXLINE);
fputs(buf, stdout);
return 0;
}
答案 0 :(得分:1)
errno
值4为EINTR
。这表示系统调用已中断。在这种情况下,SIGCHLD
正在中断accept
系统调用。请继续阅读该章。下面是它的引用,它特别指出了这个特定的示例代码:
- 由于在父系统调用(接受)中阻塞了父项时父项捕获了信号,因此内核导致
醇>accept
返回错误EINTR
(系统调用中断)。父级不处理此错误,因此中止。这个例子的目的是表明在编写捕获信号的网络程序时,我们必须认识到中断的系统调用,我们必须处理它们。
它继续解释如何设置信号以自动重启中断的系统调用。总之,请在SA_RESTART
字段中设置act.sa_flags
标记:
act.sa_flags |= SA_RESTART;