服务器只接受一次并终止

时间:2016-01-01 04:51:56

标签: linux server wait

我在第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;
}

1 个答案:

答案 0 :(得分:1)

errno值4为EINTR。这表示系统调用已中断。在这种情况下,SIGCHLD正在中断accept系统调用。请继续阅读该章。下面是它的引用,它特别指出了这个特定的示例代码:

  
      
  1. 由于在父系统调用(接受)中阻塞了父项时父项捕获了信号,因此内核导致accept返回错误EINTR(系统调用中断)。父级不处理此错误,因此中止。
  2.         

    这个例子的目的是表明在编写捕获信号的网络程序时,我们必须认识到中断的系统调用,我们必须处理它们。

它继续解释如何设置信号以自动重启中断的系统调用。总之,请在SA_RESTART字段中设置act.sa_flags标记:

act.sa_flags |= SA_RESTART;