服务器只接受一次并终止
server only accept once and terminate
我正在学习第五章的 Unix 网络编程,wait 和 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;
}
errno
值 4 是 EINTR
。这表示系统调用被中断。在这种情况下,SIGCHLD
正在中断 accept
系统调用。继续阅读该章。下面是它的引述,特别指出了这个特定的示例代码:
- Since the signal was caught by the parent while the parent was blocked in a slow system call (accept), the kernel causes
accept
to return an error of EINTR
(interrupted system call). The parent does not handle this error so it aborts.
The purpose of this example is to show that when writing network programs that catch signals, we must be cognizant of interrupted system calls, and we must handle them.
它进一步解释了如何设置信号以自动重启中断的系统调用。总之,在act.sa_flags
字段中设置SA_RESTART
标志:
act.sa_flags |= SA_RESTART;
我正在学习第五章的 Unix 网络编程,wait 和 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;
}
errno
值 4 是 EINTR
。这表示系统调用被中断。在这种情况下,SIGCHLD
正在中断 accept
系统调用。继续阅读该章。下面是它的引述,特别指出了这个特定的示例代码:
- Since the signal was caught by the parent while the parent was blocked in a slow system call (accept), the kernel causes
accept
to return an error ofEINTR
(interrupted system call). The parent does not handle this error so it aborts.The purpose of this example is to show that when writing network programs that catch signals, we must be cognizant of interrupted system calls, and we must handle them.
它进一步解释了如何设置信号以自动重启中断的系统调用。总之,在act.sa_flags
字段中设置SA_RESTART
标志:
act.sa_flags |= SA_RESTART;