APLawrence.com -  Resources for Unix and Linux Systems, Bloggers and the self-employed

NETTEST

Kevin Smith of Shade Tree Software, Inc. is a frequent contributor to the SCO newsgroups. Here he provides a small utility to exercise and test network ports. You can download the source or an OSR5 binary.

To compile the source:


cc nettest.c -o nettest -lsocket

 

For the most simple test, run "nettest -r", switch to another virtual console and run "nettest -w". Switch back to see the results.

Download Source.

Download OSR5 binary.


© 2000 Shade Tree Software, Inc.

I've been sitting on a utility to test network connectivity and throughput for a while now and thought some others might be interested.

The program is called 'nettest'. It runs in one of four modes.

  • Read

    TCP (normal connection type mode)

    Accepts multiple connections, reads and discards data. Reports transfer stats when a connection closes.

    UDP (connectionless datagrams)

    This is connectionless so it just reports stats every now and then (every MB)


  • Write

    TCP

    UDP


Both of these write N buffers of N bytes each to a given hostname and port and report transfer stats. It was originally written as four separate programs so the code is a little rough in spots...

---- Cut Here --------------------------------------------------------
/*
 * @(#)nettest.c--Test read and writes to a network port
 */

static  char *what[]={
    "@(#)nettest--Test reads/writes to a network port",
    "@(#)Copyright 2000 ShadeTree Software,Inc.",
    "@(#)Any and all uses allowed, no responsibility accepted :)",
    "@(#)STS/KBS 2apr1996",
    0,
};

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/times.h>
#include <netdb.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

#define M_NONE          0
#define M_READ          1
#define M_WRITE         2

#define MN_NONE         0
#define MN_TCPIP        1
#define MN_UDP          2

int     debugl;
char    *iam;

int     rwmode = M_NONE;
int     netmode = MN_TCPIP;

char    *hostname = "localhost";
int     port = 10001;
int     bufsz = 1024;
int     nbufs = 100;

char    ebuf[512];                      /* error messages */
int     hz;                             /* for timings */

extern  int     h_errno;

main(ac,av)
int     ac;
char    *av[];
{
    int         s;
    struct      sockaddr_in sin;
    int         c;
    struct      hostent *hp;
    char        *buf;
    int         bufr,bufw;
    int         oc;                     /* current option char */
    int         on;                     /* current string option number */
    extern      char *optarg;           /* stuff for getopt */
    extern      int optind, optopt;     /* stuff for getopt */


    iam = av[0];
    hz = sysconf(_SC_CLK_TCK);

    on = 0;
    while(( oc = getopt(ac,av,"urwdb:n:h:p:")) != -1 )
    {
        switch(oc)
        {
         case 'u':
            netmode = MN_UDP;
            break;
         case 'r':
            if (rwmode != M_NONE)
            {
                usage();
            }
            rwmode = M_READ;
            break;
         case 'w':
            if (rwmode != M_NONE)
            {
                usage();
            }
            rwmode = M_WRITE;
            break;
         case 'd':
            debugl++;
            break;
         case 'b':
            bufsz = atoi(optarg);
            break;
         case 'n':
            nbufs = atoi(optarg);
            break;
         case 'h':
            hostname = optarg;
            break;
         case 'p':
            port = atoi(optarg);
            break;
         case ':':
         case '?':
         default:
            usage();
            break;
        }
    }
    if(optind < ac)
    {
        fprintf(stderr,"Too many arguments (%s)\n",av[optind]);
        usage();
    }
    if(rwmode == M_NONE)
    {
        fprintf(stderr,"One of -r or -w is manditory\n");
        usage();
    }
    if(debugl)
    {
        fprintf(
            stderr,
            "mode = %s %s\n",
            netmode == MN_NONE ? "None" :
                netmode == MN_TCPIP ? "TCP/IP" :
                netmode == MN_UDP ? "UDP" : "???",
            rwmode == M_NONE ? "None" :
                rwmode == M_READ ? "Read" :
                rwmode == M_WRITE ? "Write" : "???"
        );
        fprintf(stderr,"bufsz = %d\n",bufsz);
        fprintf(stderr,"nbufs = %d\n",nbufs);
        fprintf(stderr,"hostname = %s\n",hostname);
        fprintf(stderr,"port = %d\n",port);
    }

    if (netmode == MN_TCPIP)
    {
        if (rwmode == M_WRITE)
        {
            return(tcpwrite());
        }
        else
        {
            return(tcpread());
        }
    }
    else
    {
        if (rwmode == M_WRITE)
        {
            return(udpwrite());
        }
        else
        {
            return(udpread());
        }
    }
    /* NOTREACHED */
}

int
tcpwrite(void)
{
    int         s;
    struct      sockaddr_in sin;
    int         c;
    struct      hostent *hp;
    char        *buf;
    int         bufr,bufw;
    int         stime, etime, totalwrites, totalbytes;
    struct      tms tms;

    if(!(buf=malloc(bufsz))) {
        perror("malloc()");
        return;
    }

    setbuf(stderr,NULL);

    hp = gethostbyname(hostname);
    if(debugl) fprintf(stderr,"gethostbyname()=0x%x\n",hp);
    if(!hp) {
        herror(hostname);
        return(2);
    }

    for(;;) {
        s=socket(AF_INET, SOCK_STREAM, 0);
        if(debugl) fprintf(stderr,"socket()=%d\n",s);
        if(s<0) {
            perror("Can't open socket");
            return(2);
        }

        /*
         * Build socket name
         */
        memset(&sin,0,sizeof(sin));
        memcpy( (char *)&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
        sin.sin_family = hp->h_addrtype;
        sin.sin_port = htons(port);
        if(debugl) fprintf(stderr,"sin.sin_addr=%s\n",inet_ntoa(sin.sin_addr));

        c=connect(s,(struct sockaddr *)&sin,sizeof(sin));
        if(debugl) fprintf(stderr,"connect()=%d\n",c);

        if(c) {
            if(debugl) {
                sprintf(buf,"Connect to port %d on %s",port,hostname);
                perror(buf);
            }
            close(s);
            sleep(5);
        } else {
            break;
        }
    }

    if(fcntl(s, F_SETFL, fcntl(s,F_GETFL,0) & O_SYNC) == -1) {
        if(debugl) perror("fcntl(O_SYNC)");
    }

    buf[0] = '\n';
    stime = etime = times(&tms);
    totalwrites = totalbytes = 0;
    for(c=0; c<nbufs;c++) {
        bufr = bufsz;
        bufw=write(s,buf,bufr);
        if(debugl) fprintf(stderr,"write()=%d\n",bufw);
        if(bufr != bufw) {
            if(debugl) fprintf(stderr,"short write!\n");
            if(bufw < 0) break;
        }
        totalwrites++;
        totalbytes += bufw;
    }

    /* show stats */
    etime = times(&tms);
    {
        float   bps,secs;

        secs = etime - stime;
        secs /= hz;
        if(secs > 0)
        {
            bps = (float)totalbytes / secs;
        }
        else
        {
            bps = 0;
        }
        fprintf(
            stderr,
            "%d writes, %d bytes in %g seconds, %.0f bps\n",
            totalwrites,
            totalbytes,
            secs,
            bps
        );
    }

    close(s);

    return(0);
}

int
tcpread(void)
{
    struct      sockaddr_in     sin;    /* socket name */
    int         s;                      /* our socket */
    int         sc;                     /* incomming connection socket */
    struct      sockaddr_in     sf;     /* socket name of connection */
    int         sflen;                  /* socket name length */
    fd_set      allmask;                /* initial select mask (our socket) */
    fd_set      rmask;                  /* current select mask (w connects) */
    int         sv;                     /* select return value */
    int         rz;                     /* read size */
    int         one = 1;
    char        *buf;
    struct      tms tms;
    struct {
        clock_t stime;
        clock_t etime;
        int     currentbytes;   /* used for status updates */
        int     totalreads;
        int     totalbytes;
    } ss[20];

    if(!(buf=malloc(bufsz))) {
        perror("malloc()");
        return;
    }

    /*
     * Create the socket (file descriptor)
     * Give up immediatly if we can't get a socket.
     */
    if((s=socket(AF_INET,SOCK_STREAM,0))<0) {
        perror("Couldn't create socket");
        return(1);
    }
    fprintf(stderr,"Created socket %d\n",s);

    /*
     * Reuse port--Easy testing
     */
    if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one))) {
        perror("setsockopt");
    }

    /*
     * Build socket name
     */
    memset(&sin,0,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);

    /*
     * Bind to socket
     */
    if(bind(s, (struct sockaddr *)&sin, sizeof(sin))) {
        sprintf(
            ebuf,
            "Couldn't bind to port %d",
            ntohs(sin.sin_port)
        );
        perror(ebuf);
        close(s);
        return(1);
    }
    fprintf(
        stderr,
        "Bound to port %d\n",
        ntohs(sin.sin_port)
    );

    /*
     * Estabilish connection queue
     */
    listen(s,5);

    /*
     * Setup select mask.
     * Initialize to our socket only
     */
    FD_ZERO(&allmask);
    FD_SET(s,&allmask);

    /*
     * Wait for activity
     */
    for(;;) {
        if(debugl) fprintf(stderr,"Waiting...");

        memcpy(&rmask,&allmask,sizeof(allmask));
        sv = select(20,&rmask,0,0,0);
        if(debugl) putc(' ',stderr);
        if(sv<0) {
            perror("select");
            continue;
        }

        /*
         * Check for connection attempt (our socket)
         */
        if(FD_ISSET(s,&rmask)) {

            fprintf(stderr,"Incomming connection...\n");

            FD_CLR(s,&rmask);           /* Clear ourselvs from current set */
            sflen = sizeof(struct sockaddr_in);
            sc = accept(s,(struct sockaddr*)&sf, &sflen);
            if(sc<0) {
                perror("accept");
                continue;
            }

            fprintf(
                stderr,
                "   socket=%d, ip=%s, port=%d\n",
                sc,
                inet_ntoa(sf.sin_addr),
                ntohs(sf.sin_port)
            );

            FD_SET(sc,&allmask);        /* Add to active set */
            ss[sc].stime = times(&tms);
            ss[sc].etime = ss[sc].stime;
            ss[sc].totalreads = 0;
            ss[sc].totalbytes = 0;
        }

        /*
         * Check for other activity
         */
        for(sc = 3; sc < 20; sc++) {
            if(FD_ISSET(sc,&rmask)) {
                FD_CLR(sc,&rmask);
                errno = 0;
                rz = read(sc,buf,bufsz);
                if(rz>0) {
                    ss[sc].totalreads++;
                    ss[sc].totalbytes += rz;
                    if(debugl) {
                        fprintf(
                            stderr,
                            "(%d) read()=%d (errno=%d), total=%d\n",
                            sc,rz,errno,ss[sc].totalbytes
                        );
                    } else {
                        ss[sc].currentbytes += rz;
                        if(ss[sc].currentbytes >= 1000000) {
                            fprintf(stderr,"\r(%d) %d ",sc,ss[sc].totalbytes);
                            ss[sc].currentbytes = 0;
                        }
                    }
                }
                if(rz <= 0) {
                    fprintf(stderr,"\r(%d) %d ",sc,ss[sc].totalbytes);
                    if(rz==0) {
                        fprintf(stderr,"EOF--disconnecting\n");
                    } else {
                        perror("read from socket--disconnecting");
                    }
                    ss[sc].etime = times(&tms);
                    close(sc);
                    FD_CLR(sc,&allmask);
                    {
                        float   bps,secs;

                        secs = ss[sc].etime - ss[sc].stime;
                        secs /= hz;
                        if(secs > 0)
                        {
                            bps = (float)ss[sc].totalbytes / secs;
                        }
                        else
                        {
                            bps = 0;
                        }
                        fprintf(
                            stderr,
                            "(%d) %d reads, %d bytes in %g seconds, %.0f bps\n",
                            sc,
                            ss[sc].totalreads,
                            ss[sc].totalbytes,
                            secs,
                            bps
                        );
                    }
                    continue;
                }
            }
        }
    }
}

int
udpwrite(void)
{
    int         s;
    struct      sockaddr_in sin;
    int         c;
    struct      hostent *hp;
    char        *buf;
    int         bufr;
    int         stime, etime, totalwrites, totalbytes;
    struct      tms tms;

    if(!(buf=malloc(bufsz))) {
        perror("malloc()");
        return;
    }

    setbuf(stderr,NULL);

    hp = gethostbyname(hostname);
    if(debugl) fprintf(stderr,"gethostbyname()=0x%x\n",hp);
    if(!hp) {
        herror(hostname);
        return(2);
    }

    s=socket(AF_INET, SOCK_DGRAM, 0);
    if(debugl) fprintf(stderr,"socket()=%d\n",s);
    if(s<0) {
        perror("Can't open socket");
        return(2);
    }

    /*
     * Build socket name
     */
    memset(&sin,0,sizeof(sin));
    memcpy( (char *)&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
    sin.sin_family = hp->h_addrtype;
    sin.sin_port = htons(port);
    if(debugl) fprintf(stderr,"sin.sin_addr=%s\n",inet_ntoa(sin.sin_addr));

    buf[0] = '\n';
    stime = etime = times(&tms);
    totalwrites = totalbytes = 0;
    for(c=0; c<nbufs;c++) {
        bufr = bufsz;
        if(
            sendto(
                s,
                (void *)buf,
                bufr,
                0,
                (struct sockaddr *)&sin,sizeof(sin)
            ) < 0
        )
        {
            perror("sendto()");
        } else {
            if(debugl) fprintf(stderr,"sendto(%d,0x%x,%d)\n",s,buf,bufr);
            totalwrites++;
            totalbytes += bufr;
        }
    }

    /* show stats */
    etime = times(&tms);
    {
        float   bps,secs;

        secs = etime - stime;
        secs /= hz;
        if(secs > 0)
        {
            bps = (float)totalbytes / secs;
        }
        else
        {
            bps = 0;
        }
        fprintf(
            stderr,
            "%d writes, %d bytes in %g seconds, %.0f bps\n",
            totalwrites,
            totalbytes,
            secs,
            bps
        );
    }

    close(s);

    return(0);
}

int
udpread(void)
{
    struct      sockaddr_in     sin;    /* socket name */
    int         s;                      /* our socket */
    int         rz;                     /* read size */
    int         one = 1;
    char        *buf;
    int         currentreads, currentbytes;
    int         stime, etime, totalreads, totalbytes;
    struct      tms tms;

    if(!(buf=malloc(bufsz))) {
        perror("malloc()");
        return;
    }

    /*
     * Create the socket (file descriptor)
     * Give up immediatly if we can't get a socket.
     */
    if((s=socket(AF_INET,SOCK_DGRAM,0))<0) {
        perror("Couldn't create socket");
        return(1);
    }
    fprintf(stderr,"Created socket %d\n",s);

    /*
     * Reuse port--Easy testing
     */
    if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one))) {
        perror("setsockopt");
    }

    /*
     * Build socket name
     */
    memset(&sin,0,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(port);

    /*
     * Bind to socket
     */
    if(bind(s, (struct sockaddr *)&sin, sizeof(sin))) {
        sprintf(
            ebuf,
            "Couldn't bind to port %d",
            ntohs(sin.sin_port)
        );
        perror(ebuf);
        close(s);
        return(1);
    }
    fprintf(
        stderr,
        "Bound to port %d\n",
        ntohs(sin.sin_port)
    );

    currentreads = currentbytes = totalbytes = totalreads = 0;
    stime = etime = times(&tms);
    for(;;) {
        if(debugl) fprintf(stderr,"Waiting...");
        rz = read(s,buf,bufsz);
        if(rz>0) {
            currentbytes += rz;
            currentreads++;
            totalbytes += rz;
            totalreads++;
            if(debugl) {
                fprintf(
                    stderr,
                    "(%d) read()=%d (errno=%d), total=%d\n",
                    s,rz,errno,totalbytes
                );
            }
            if(currentbytes >= 1000000) {

                /* show stats */
                etime = times(&tms);
                {
                    float       bps,secs;

                    secs = etime - stime;
                    secs /= hz;
                    if(secs > 0)
                    {
                        bps = (float)currentbytes / secs;
                    }
                    else
                    {
                        bps = 0;
                    }
                    fprintf(
                        stderr,
                        "%d reads, %d bytes in %g seconds, %.0f bps\n",
                        currentreads,
                        currentbytes,
                        secs,
                        bps
                    );
                }
                currentreads = currentbytes = 0;
                stime = etime;
            }
        }
        if(rz <= 0) {
            fprintf(stderr,"\r(%d) %d ",s,totalbytes);
            if(rz==0) {
                fprintf(stderr,"EOF--disconnecting\n");
            } else {
                perror("read from socket--disconnecting");
            }
        }
    }
}

int
usage(void)
{
    fprintf(
        stderr,
        "usage: %s {-r|-w} [-u] [-d] [-hhostname] [-pportnumber] [-bbufsz] [-nnbufs]\n",
        iam
    );
    fprintf(stderr,"       -r (read) or -w (write) manditory/exclusive\n");
    fprintf(stderr,"       -u for UDP packets\n");
    fprintf(stderr,"       -d enables debug messages\n");
    fprintf(stderr,"       Default hostname is %s\n",hostname);
    fprintf(stderr,"       Default port is %d\n",port);
    fprintf(stderr,"       Default bufsz is %d\n",bufsz);
    fprintf(stderr,"       Default nbufs is %d\n",nbufs);
    fprintf(stderr,"       Note: hostname,nbufs ignored if not -r\n");
    exit(1);
}
---- Cut Here --------------------------------------------------------
 


Got something to add? Send me email.





(OLDER)    <- More Stuff -> (NEWER)    (NEWEST)   

Printer Friendly Version

-> -> NETTEST network port exercizor




Increase ad revenue 50-250% with Ezoic


More Articles by © Shade Tree Software Inc



Kerio Samepage


Have you tried Searching this site?

Unix/Linux/Mac OS X support by phone, email or on-site: Support Rates

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.

Contact us





The difference between e-mail and regular mail is that computers handle e-mail, and computers never decide to come to work one day and shoot all the other computers. (Jamais Cascio)

Just because they've sold you an IP based phone system doesn't mean they know anything about IP, does it? (Tony Lawrence)












This post tagged: