_HIPPI AND HIGH-PERFORMANCE LANS_ by Andy Nicholson [LISTING ONE] /* echo.h - header file for the echo example programs */ #define BUFSIZE 512 #define ECHOPORT 7500 #define ECHO_REQUEST 1 #define ECHO_REPLY 2 [LISTING TWO] /* echos.c -- The echo service server program */ #include #include #include #include #include "echo.h" main() { char buf[BUFSIZE]; int s, c; struct sockaddr_in sin, peer; int peerlen; int mlen; /* get a socket */ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("can't open socket"); exit(1); } /* bind to local address and echo port */ bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = ECHOPORT; if (bind(s, &sin, sizeof(sin)) == -1) { perror("cannot bind"); close(s); exit(1); } /* start listening for connections */ if (listen(s, 5) == -1) { perror("cannot listen"); close(s); exit(1); } /* accept and process incoming messages */ while (1) { if ((c = accept(s, &peer, &peerlen)) == -1) { perror("cannot accept"); close(s); exit(1); } /* simple processing, read message, echo it back */ if ((mlen = read(c, buf, BUFSIZE)) == -1) { perror("read error"); close(c); continue; } if (write(c, buf, mlen) != mlen) { perror("write error"); close(c); continue; } printf("%d byte message received and echoed\n", mlen); close(c); } } /* end of main */ [LISTING THREE] /* echoc.c -- The echo service client program */ #include #include #include #include #include "echo.h" main(argc, argv) int argc; char **argv; { char buf[BUFSIZE]; int s; struct sockaddr_in sin; if (argc < 2) { printf("must specify a server in internet dot notation\n"); exit(1); } /* get a socket */ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("can't open socket"); exit(1); } /* bind to local address and available port */ bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; if (bind(s, &sin, sizeof(sin)) == -1) { perror("cannot bind"); close(s); exit(1); } /* connect to echo server at echo port */ bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = ECHOPORT; sin.sin_addr.s_addr = inet_addr(argv[1]); if (connect(s, &sin, sizeof(sin)) == -1) { perror("cannot connect"); close(s); exit(1); } /* send a message to be echoed */ if (write(s, buf, BUFSIZE) != BUFSIZE) { perror("write error"); exit(1); } /* read the echoed message back */ if (read(s, buf, BUFSIZE) != BUFSIZE) { perror("read error"); exit(1); } printf("%d byte message echoed by echo server\n", BUFSIZE); close(s); exit(0); } /* end of main */ [LISTING FOUR] /* echop.c -- The echo service peer program */ #include #include #include #include #include #include "echo.h" main(argc, argv) int argc; char **argv; { int s; struct sockaddr_in sin; int status; int width; fd_set readfds, writefds, exceptfds; struct timeval timeout; if (argc < 2) { printf("must specify a peer in internet dot notation\n"); exit(1); } /* setup passive socket */ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("can't open passive socket"); exit(1); } /* bind to local address and echo port */ bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = ECHOPORT; if (bind(s, &sin, sizeof(sin)) == -1) { perror("cannot bind"); close(s); exit(1); } /* start listening for connections */ if (listen(s, 5) == -1) { perror("cannot listen"); close(s); exit(1); } /* initial select parameters */ FD_ZERO(&writefds); FD_ZERO(&exceptfds); width = s+1; /* only file descriptor we want to check */ timeout.tv_sec = 0; /* set timeval for polling */ timeout.tv_usec = 0; while (1) { /* check for and process incoming connection requests */ FD_SET(s, &readfds); while ((status = select(width, &readfds, &writefds, &exceptfds, &timeout)) > 0) { do_respond(s); FD_SET(s, &readfds); } if (status == -1) { perror("select failed"); } do_request(argv[1]); } } /* end of main */ int do_respond(s) int s; { int c; struct sockaddr_in peer; int peerlen = sizeof(peer); if ((c = accept(s, &peer, &peerlen)) == -1) { perror("accept failed"); return(-1); } do_echo(c); close(c); return(0); } /* end of do_respond */ int do_request(dst) char *dst; { int s; struct sockaddr_in sin; static pid_t pid = 0; int status; /* Wait for child if we have already forked. */ if (pid) { wait(&status); pid = 0; } /* get a socket */ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("can't open socket"); return(-1); } /* bind to local address and available port */ bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; if (bind(s, &sin, sizeof(sin)) == -1) { perror("cannot bind"); return(-1); } /* connect to echo server at echo port */ bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = ECHOPORT; sin.sin_addr.s_addr = inet_addr(dst); if (connect(s, &sin, sizeof(sin)) == -1) { perror("connection failed"); close(s); return(-1); } /* fork process to be form active request */ if ((pid = fork()) == -1) { perror("Cannot fork"); pid = 0; return(-1); } /* return if parent so we can go back and look for incoming * service requests. */ if (pid > 0) { close(s); return(0); } /* child uses echo service */ do_echo(s); close(s); exit(0); } /* end of do_request */ int do_echo(s) int s; { char buf[BUFSIZE]; int recvlen; int sendlen = BUFSIZE; /* send a message to be echoed */ buf[0] = ECHO_REQUEST; if (write(s, buf, sendlen) != sendlen) { perror("sending: write error"); exit(1); } printf("sent echo request\n"); /* read an incoming message */ if ((recvlen = read(s, buf, BUFSIZE)) == -1) { perror("reading message: read error"); exit(1); } /* echo message if it is an echo request */ if (buf[0] == ECHO_REQUEST) { buf[0] = ECHO_REPLY; if (write(s, buf, recvlen) != recvlen) { perror("echoing: write error"); exit(1); } printf("received echo request - sent echo reply\n"); } else { /* must be reply */ printf("received echo reply\n"); } /* read another incoming message */ if ((recvlen = read(s, buf, BUFSIZE)) == -1) { perror("reading message: read error"); exit(1); } /* echo message if it is an echo request */ if (buf[0] == ECHO_REQUEST) { buf[0] = ECHO_REPLY; if (write(s, buf, recvlen) != recvlen) { perror("echoing: write error"); exit(1); } printf("received echo request - sent echo reply\n"); } else { /* must be reply */ printf("received echo reply\n"); } return(0); } /* end of do_echo */