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