测试用客户程序

unix网络编程卷一
服务器设计范式之TCP测试用客户程序
//参数输入 主机名或ip地址 , 服务器端口 , 客户fork子程序数 , 子进程发送请求数 , 服务器返送数据字节数
运行:./client 127.0.0.1 8888 1 5000 4000

    #define _GNU_SOURCE  
    #include    <sys/wait.h>  
    #include    <stdio.h>  
    #include    <sys/socket.h>  
    #include    <netdb.h>  
    #include    <stdlib.h>  
    #include    <syslog.h>  
    #include    <string.h>  
    #include    <strings.h>  
    #include    <errno.h>  
    #include    <stdarg.h>  
    #include    <sys/types.h>  
    #include    <unistd.h>  

    #define MAXLINE     4096    /* max text line length */  
    int daemon_proc;        /* set nonzero by daemon_init() */  
    #define MAXN    16384       /* max # bytes to request from server */  
    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);  
    }  

    pid_t Fork(void)  
    {  
        pid_t pid;  

        if ((pid = fork()) == -1)  
            err_sys("fork error");  
        return (pid);  
    }  

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

    int tcp_connect(const char *host, const char *serv)  
    {  
        int sockfd, n;  
        struct addrinfo hints, *res, *ressave;  

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

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

        do {  
            sockfd =  
                socket(res->ai_family, res->ai_socktype, res->ai_protocol);  
            if (sockfd < 0)  
                continue;   /* ignore this one */  

            if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)  
                break;  /* success */  

            Close(sockfd);  /* ignore this one */  
        } while ((res = res->ai_next) != NULL);  

        if (res == NULL)    /* errno set from final connect() */  
            err_sys("tcp_connect error for %s, %s", host, serv);  

        freeaddrinfo(ressave);  

        return (sockfd);  
    }  

    int Tcp_connect(const char *host, const char *serv)  
    {  
        return (tcp_connect(host, serv));  
    }  

    void Write(int fd, void *ptr, int nbytes)  
    {  
        if (write(fd, ptr, nbytes) != nbytes)  
            err_sys("write error");  
    }  
    ssize_t                     /* Read "n" bytes from a descriptor. */  
    readn(int fd, void *vptr, size_t n)  
    {  
        size_t  nleft;  
        ssize_t nread;  
        char    *ptr;  

        ptr = vptr;  
        nleft = n;  
        while (nleft > 0) {  
            if ( (nread = read(fd, ptr, nleft)) < 0) {  
                if (errno == EINTR)  
                    nread = 0;      /* and call read() again */  
                else  
                    return(-1);  
            } else if (nread == 0)  
                break;              /* EOF */  

            nleft -= nread;  
            ptr   += nread;  
        }  
        return(n - nleft);      /* return >= 0 */  
    }  
    ssize_t  
    Readn(int fd, void *ptr, size_t nbytes)  
    {  
        ssize_t     n;  

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

    int main(int argc, char **argv)  
    {  
        int i, j, fd, nchildren, nloops, nbytes;  
        pid_t pid;  
        ssize_t n;  
        char request[MAXLINE], reply[MAXN];  

        if (argc != 6)  
            err_quit  
                ("usage: client <hostname or IPaddr> <port> <#children> "  
                 "<#loops/child> <#bytes/request>");  

        nchildren = atoi(argv[3]);  
        nloops = atoi(argv[4]);  
        nbytes = atoi(argv[5]);  
        snprintf(request, sizeof(request), "%d\n", nbytes); /* newline at end */  

        for (i = 0; i < nchildren; i++) {  
            if ((pid = Fork()) == 0) {  /* child */  
                for (j = 0; j < nloops; j++) {  
                    fd = Tcp_connect(argv[1], argv[2]);  

                    Write(fd, request, strlen(request));  

                    if ((n = Readn(fd, reply, nbytes)) != nbytes)  
                        err_quit("server returned %d bytes", n);  

                    Close(fd);  /* TIME_WAIT on client, not server */  
                }  
                printf("child %d done\n", i);  
                exit(0);  
            }  
            /* parent loops around to fork() again */  
        }  

        while (wait(NULL) > 0)   /* now parent waits for all children */  
            ;  
        if (errno != ECHILD)  
            err_sys("wait error");  

        exit(0);  
    }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值