简单回射程序之处理僵死进程版服务器程序

时间:2019-04-12
本文章向大家介绍简单回射程序之处理僵死进程版服务器程序,主要包括简单回射程序之处理僵死进程版服务器程序使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、server.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>

#define SERV_PORT 9999
#define MAXLINE 4096
#define LISTENQ 1024
#define SA struct sockaddr

typedef void Sigfunc(int);

void str_echo(int);
void sig_chld(int);
ssize_t writen(int, const void*, size_t);
Sigfunc *signal(int, Sigfunc*);

int main(int argc, char *argv[]) {
    int listenfd, connfd;
    pid_t childpid;
    socklen_t clilen;
    struct sockaddr_in cliaddr, servaddr;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    bind(listenfd, (SA *)&servaddr, sizeof(servaddr));

    listen(listenfd, LISTENQ); 

    signal(SIGCHLD, sig_chld); /* Install signal processing function */

    for ( ; ; ) {
        clilen = sizeof(cliaddr);
        connfd = accept(listenfd, (SA *)&cliaddr, &clilen);

        if ( (childpid = fork()) == 0) { /* Generate child processes to handle foreign connections */
            close(listenfd);
            str_echo(connfd);
            exit(0);
        }
        close(connfd);
    }
    close(listenfd);
    exit(0);
}

void str_echo(int sockfd) {
    ssize_t n;
    char buf[MAXLINE];

    again:
    while ( (n = read(sockfd, buf, MAXLINE)) > 0) {
        writen(sockfd, buf, n);
        bzero(buf, sizeof(buf));
    }
    if (n < 0 && errno == EINTR) {
        goto again;
    } else if (n < 0) {
        perror("read");
    }
}

二、writen.c

#include <unistd.h>
#include <errno.h>

ssize_t writen(int fd, const void *vptr, size_t n) {
    size_t nleft;
    ssize_t nwriten;
    const char *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nwriten = write(fd, ptr, nleft)) <= 0) {
            if (nwriten < 0 && errno) {
                nwriten = 0; /* call write() again */
            } else {
                return (-1); /* error */
            }
        } 
        nleft -= nwriten;
        ptr += nwriten;
    }
    return (n - nwriten);
}

三、signal.c

#include <signal.h>

typedef void Sigfunc(int);

Sigfunc *signal(int signo, Sigfunc *func) {
    struct sigaction act, oact;

    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
        act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
    } else {
#ifdef SA_RESTART
    act.sa_flags |= SA_RESTART;   /* SVR4, 4.4BSD */
#endif
    }
    if (sigaction(signo, &act, &oact) < 0) {
    return SIG_ERR;
    }
    return (oact.sa_handler);
}

四、sig_chld.c

#include <stdio.h>
#include <sys/wait.h>

void sig_chld(int signo) {
    pid_t pid;
    int stat;
    
    pid = wait(&stat);
    printf("child %d terminated\n", pid);
    return;
}

五、Makefile

target=server
cc=gcc
$(target):writen.o server.o signal.o sig_chld.o
        $(cc)  writen.o server.o signal.o sig_chld.o -o $(target)
writen.o:writen.c
        $(cc) -c writen.c -o writen.o
server.o:server.c
        $(cc) -c server.c -o server.o
signal.o:
        $(cc) -c signal.c -o signal.o
sig_chld.o:
        $(cc) -c sig_chld.c -o sig_chld.o
clean:
        rm -rf *.o $(target)