简单迭代服务器

unix网络编程服务器编程范式之简单迭代服务器
运行,./server 8888

    #define _GNU_SOURCE  
    #include    <signal.h>  
    #include    <unistd.h>  
    #include    <string.h>  
    #include    <stdio.h>  
    #include    <errno.h>  
    #include    <strings.h>  
    #include    <stdlib.h>  
    #include    <sys/socket.h>  
    #include    <sys/types.h>  
    #include    <netdb.h>  
    #include    <syslog.h>  
    #include    <stdarg.h>  
    #include    <sys/resource.h>  
    #define LISTENQ     1024    /* 2nd argument to listen() */  
    #define MAXLINE     4096    /* max text line length */  
    #define MAXN    16384       /* max # bytes to request from server */  
    typedef void Sigfunc(int);  /* for signal handlers */  
    int daemon_proc;        /* set nonzero by daemon_init() */  

    void sig_int(int signo)  
    {  
        void pr_cpu_time(void);  

        pr_cpu_time();  
        exit(0);  
    }  

    void err_doit(int errnoflag, int level, const char *fmt, va_list ap)  
    {  
        int errno_save, n;  
        char buf[MAXLINE + 1];  

        errno_save = errno; /* value caller might want printed */  
    #ifdef  HAVE_VSNPRINTF  
        vsnprintf(buf, MAXLINE, fmt, ap);   /* safe */  
    #else  
        vsprintf(buf, fmt, ap); /* not safe */  
    #endif  
        n = strlen(buf);  
        if (errnoflag)  
            snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));  
        strcat(buf, "\n");  

        if (daemon_proc) {  
            syslog(level, "%s", buf);  
        } else {  
            fflush(stdout); /* in case stdout and stderr are the same */  
            fputs(buf, stderr);  
            fflush(stderr);  
        }  
        return;  
    }  

    void err_quit(const char *fmt, ...)  
    {  
        va_list ap;  

        va_start(ap, fmt);  
        err_doit(0, LOG_ERR, fmt, ap);  
        va_end(ap);  
        exit(1);  
    }  

    void err_sys(const char *fmt, ...)  
    {  
        va_list ap;  

        va_start(ap, fmt);  
        err_doit(1, LOG_ERR, fmt, ap);  
        va_end(ap);  
        exit(1);  
    }  

    void pr_cpu_time(void)  
    {  
        double user, sys;  
        struct rusage myusage, childusage;  

        if (getrusage(RUSAGE_SELF, &myusage) < 0)  
            err_sys("getrusage error");  
        if (getrusage(RUSAGE_CHILDREN, &childusage) < 0)  
            err_sys("getrusage error");  

        user = (double)myusage.ru_utime.tv_sec +  
            myusage.ru_utime.tv_usec / 1000000.0;  
        user += (double)childusage.ru_utime.tv_sec +  
            childusage.ru_utime.tv_usec / 1000000.0;  
        sys = (double)myusage.ru_stime.tv_sec +  
            myusage.ru_stime.tv_usec / 1000000.0;  
        sys += (double)childusage.ru_stime.tv_sec +  
            childusage.ru_stime.tv_usec / 1000000.0;  

        printf("\nuser time = %g, sys time = %g\n", user, sys);  
    }  

    void Setsockopt(int fd, int level, int optname, const void *optval,  
            socklen_t optlen)  
    {  
        if (setsockopt(fd, level, optname, optval, optlen) < 0)  
            err_sys("setsockopt error");  
    }  

    void Close(int fd)  
    {  
        if (close(fd) == -1)  
            err_sys("close error");  
    }  

    void Listen(int fd, int backlog)  
    {  
        char *ptr;  

        /*4can override 2nd argument with environment variable */  
        if ((ptr = getenv("LISTENQ")) != NULL)  
            backlog = atoi(ptr);  

        if (listen(fd, backlog) < 0)  
            err_sys("listen error");  
    }  

    int tcp_listen(const char *host, const char *serv, socklen_t * addrlenp)  
    {  
        int listenfd, n;  
        const int on = 1;  
        struct addrinfo hints, *res, *ressave;  

        bzero(&hints, sizeof(struct addrinfo));  
        hints.ai_flags = AI_PASSIVE;  
        hints.ai_family = AF_UNSPEC;  
        hints.ai_socktype = SOCK_STREAM;  

        if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)  
            err_quit("tcp_listen error for %s, %s: %s",  
                 host, serv, gai_strerror(n));  
        ressave = res;  

        do {  
            listenfd =  
                socket(res->ai_family, res->ai_socktype, res->ai_protocol);  
            if (listenfd < 0)  
                continue;   /* error, try next one */  

            Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));  
            if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)  
                break;  /* success */  

            Close(listenfd);    /* bind error, close and try next one */  
        } while ((res = res->ai_next) != NULL);  

        if (res == NULL)    /* errno from final socket() or bind() */  
            err_sys("tcp_listen error for %s, %s", host, serv);  

        Listen(listenfd, LISTENQ);  

        if (addrlenp)  
            *addrlenp = res->ai_addrlen; /* return size of protocol address */  

        freeaddrinfo(ressave);  

        return (listenfd);  
    }  

    int Tcp_listen(const char *host, const char *serv, socklen_t * addrlenp)  
    {  
        return (tcp_listen(host, serv, addrlenp));  
    }  

    void *Malloc(size_t size)  
    {  
        void *ptr;  

        if ((ptr = malloc(size)) == NULL)  
            err_sys("malloc error");  
        return (ptr);  
    }  

    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, 44BSD */  
    #endif  
        }  
        if (sigaction(signo, &act, &oact) < 0)  
            return (SIG_ERR);  
        return (oact.sa_handler);  
    }  

    Sigfunc *Signal(int signo, Sigfunc * func)  
    {               /* for our signal() function */  
        Sigfunc *sigfunc;  

        if ((sigfunc = signal(signo, func)) == SIG_ERR)  
            err_sys("signal error");  
        return (sigfunc);  
    }  

    int Accept(int fd, struct sockaddr *sa, socklen_t * salenptr)  
    {  
        int n;  

     again:  
        if ((n = accept(fd, sa, salenptr)) < 0) {  
    #ifdef  EPROTO  
            if (errno == EPROTO || errno == ECONNABORTED)  
    #else  
            if (errno == ECONNABORTED)  
    #endif  
                goto again;  
            else  
                err_sys("accept error");  
        }  
        return (n);  
    }  

    static int read_cnt;  
    static char *read_ptr;  
    static char read_buf[MAXLINE];  
    static ssize_t my_read(int fd, char *ptr)  
    {  

        if (read_cnt <= 0) {  
     again:  
            if ((read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {  
                if (errno == EINTR)  
                    goto again;  
                return (-1);  
            } else if (read_cnt == 0)  
                return (0);  
            read_ptr = read_buf;  
        }  

        read_cnt--;  
        *ptr = *read_ptr++;  
        return (1);  
    }  

    ssize_t readline(int fd, void *vptr, int maxlen)  
    {  
        ssize_t n, rc;  
        char c, *ptr;  

        ptr = vptr;  
        for (n = 1; n < maxlen; n++) {  
            if ((rc = my_read(fd, &c)) == 1) {  
                *ptr++ = c;  
                if (c == '\n')  
                    break;  /* newline is stored, like fgets() */  
            } else if (rc == 0) {  
                *ptr = 0;  
                return (n - 1); /* EOF, n - 1 bytes were read */  
            } else  
                return (-1);    /* error, errno set by read() */  
        }  

        *ptr = 0;       /* null terminate like fgets() */  
        return (n);  
    }  

    ssize_t Readline(int fd, void *ptr, size_t maxlen)  
    {  
        ssize_t n;  

        if ((n = readline(fd, ptr, maxlen)) < 0)  
            err_sys("readline error");  
        return (n);  
    }  

    ssize_t             /* Write "n" bytes to a descriptor. */  
    writen(int fd, const void *vptr, size_t n)  
    {  
        size_t nleft;  
        ssize_t nwritten;  
        const char *ptr;  

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

            nleft -= nwritten;  
            ptr += nwritten;  
        }  
        return (n);  
    }  

    void Writen(int fd, void *ptr, int nbytes)  
    {  
        if (writen(fd, ptr, nbytes) != nbytes)  
            err_sys("writen error");  
    }  

    void web_child(int sockfd)  
    {  
        int ntowrite;  
        ssize_t nread;  
        char line[MAXLINE], result[MAXN];  

        for (;;) {  
            if ((nread = Readline(sockfd, line, MAXLINE)) == 0)  
                return; /* connection closed by other end */  

            /* 4line from client specifies #bytes to write back */  
            ntowrite = atol(line);  
            if ((ntowrite <= 0) || (ntowrite > MAXN))  
                err_quit("client request for %d bytes", ntowrite);  

            Writen(sockfd, result, ntowrite);  
        }  
    }  

    int main(int argc, char **argv)  
    {  
        int listenfd, connfd;  
        void sig_int(int), web_child(int);  
        socklen_t clilen, addrlen;  
        struct sockaddr *cliaddr;  

        if (argc == 2)  
            listenfd = Tcp_listen(NULL, argv[1], &addrlen);  
        else if (argc == 3)  
            listenfd = Tcp_listen(argv[1], argv[2], &addrlen);  
        else  
            err_quit("usage: serv00 [ <host> ] <port#>");  
        cliaddr = Malloc(addrlen);  

        Signal(SIGINT, sig_int);  

        for (;;) {  
            clilen = addrlen;  
            connfd = Accept(listenfd, cliaddr, &clilen);  

            web_child(connfd);  /* process the request */  

            Close(connfd);  /* parent closes connected socket */  
        }  
    }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值