Я изучаю сетевое программирование Unix в главе 5, функции wait и waitpid. Тестирую функцию жду. Сначала я запускаю серверное приложение, а затем клиентское (повторяю ./a.out несколько раз). Но сервер может принять запрос только один раз и завершиться. Errno - 4.

/* server.c
 *
 *  gcc server.c -o server
 *  ./server &     (run in background)
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 

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 
#include 
#include 
#include 
#include 
#include 
#include 

#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;
}

hel

Ответов: 1

Ответы (1)

номер ошибки значение 4 равно EINTR. Это указывает на то, что системный вызов был прерван. В этом случае SIGCHLD прерывает системный вызов accept. Продолжайте читать в этой главе. Ниже приводится его цитата, которая конкретно указывает на это для этого конкретного примера кода:

  1. Поскольку сигнал был пойман родителем, в то время как родительский блок был заблокирован медленным системным вызовом (accept), ядро ​​заставляет accept возвращать ошибку EINTR (прерванная система вызов). Родитель не обрабатывает эту ошибку, поэтому она прерывается.

Цель этого примера - показать, что при написании сетевых программ, которые улавливают сигналы, мы должны знать о прерванных системных вызовах и обрабатывать их.

Далее объясняется, как можно настроить сигнал для автоматического перезапуска прерванных системных вызовов. Таким образом, установите флаг SA_RESTART в поле act.sa_flags:

act.sa_flags |= SA_RESTART;

2022 WebDevInsider