网络编程之Client/Server Design Testbench(二)

1. 前言

UNP中给出了一个简单的testbench的模型,笔者也会根据该模型,略微修改后,最为自己的testbench使用。不得不提到UNP给出的testbench的缺点:手动键入crtl+c结束测试,这将给测试带来非常大的不准确性。

2. 笔者自己的版本
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#define KEY 0x1 /* key for first message queue */
#define MAXLINE 20
#define handle_error(msg) \
	          do { perror(msg); exit(EXIT_FAILURE); } while (0)


#define MAXN 16384 /* max # bytes to request from server */

typedef struct {
    long mtype;
    char mtext[MAXLINE];
} Mymsg;

ssize_t writen(int fd, const void *vptr, size_t n);
ssize_t readn(int fd, void *vptr, size_t n);
void sig_int(int );


int ident;

int main(int argc, char **argv)
{
    int i, j, sockfd, nchildren, nloops, nbytes;
    pid_t pid;
    in_port_t port;
    Mymsg msg;
    ssize_t n;
    struct sockaddr_in servaddr;
    char request[MAXLINE], reply[MAXN];
    if (argc != 6)
        errx(1, "usage: client <hostname or IPaddr> <port> <#children> <#loops/child> <#bytes/request>");
    port = atoi(argv[2]);
    nchildren = atoi(argv[3]);
    nloops = atoi(argv[4]);
    nbytes = atoi(argv[5]);
    snprintf(request, sizeof(request), "%d\n", nbytes); /* newline at end */
    
    //在我们人为结束该进程的时候,也需要删除刚刚创建的IPC
    if(signal(SIGINT, sig_int) == SIG_ERR)
		handle_error("signal");
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);
    if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) == -1)
    	handle_error("inet_pton");

    if((ident=msgget(KEY,IPC_CREAT|0660)) == -1 )
	handle_error("msgget");

    for (i = 0; i < nchildren; i++) {
        if ((pid = fork()) <0)
            handle_error("fork");
        if ( pid == 0) { /* child */
		    //debug
		    //printf("child %d start\n",i);
            for (j = 0; j < nloops; j++) {
                if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
                    handle_error("socket");
                if(connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1)
                    handle_error("connect");
                if(writen(sockfd, request, strlen(request)) == -1)
                    handle_error("writen");
                if ( (n = readn(sockfd, reply, nbytes)) != nbytes)
                    handle_error("readn");
				//debug
				//printf("childe %d, read bytes:%d\n",i,n);
                if(close(sockfd) == -1)
                    handle_error("close");
            }
		   // debug
           // printf("child %d done\n", i);
            exit(0);
        }
    /* parent loops around to fork() again */
    }
    while (wait(NULL) > 0);
        if (errno != ECHILD)
             errx(1,"wait error");
    msg.mtype=1;
    memcpy(msg.mtext,"start",6);
    if (msgsnd(ident,&msg,MAXLINE,0) == -1 )
	handle_error("msgrcv");
    if (msgrcv(ident,&msg,MAXLINE,2,0) ==  -1)
	handle_error("msgrcv");
    if (msgctl(ident,IPC_RMID,NULL) == -1)
	handle_error("msgctl");
    exit(0);
}
void sig_int(int signo)
{
    if (msgctl(ident,IPC_RMID,NULL) == -1)                                                                           
	handle_error("msgctl");
    exit(0);   
}

ssize_t 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);
}


ssize_t 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 */
}

3. 简单介绍程序

笔者自己画的简单的测试流程图:
这里写图片描述

  • 因为进行server的压力测试的时候,笔者是在同一主机上。所以采用message IPC的进程间通信方式,来同步server和testbench。
  • 当testbench所有的client完成TCP的通信的时候,由testbench发送结束信息给被测试的server。
  • server收到message的时候,代表自身需要结束,此时打印自身运行时间,并回复一个信息给testbench,testbench在另一端检测到该信息,结束自身,整个测试过程结束。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值