Superservers
#include "funcs.h" /****** Skeleton for a superserver based
****** on using exec to provide service.
******/
#define PASSIVE_MAX 2
sigjmp_buf env;
main()
{
int passive[2], i;
short curport = 3071;
fd_set rds, savefds;
struct sigaction sa;
void reaper(int signum);
int set_up_socket(short port);
void callexec(int *passive, fd_set ready);
FD_ZERO(&savefds);
for (i = 0; i < PASSIVE_MAX; i++, curport++)
{
passive[i] = set_up_socket(curport);
FD_SET(passive[i], &savefds);
}
sa.sa_handler = reaper;
sa.sa_flags = 0;
Sigfillset(&sa.sa_mask);
Sigaction(SIGCHLD, &sa, NULL);
while (1)
{
sigsetjmp(env,1);
memcpy(&rds, &savefds, sizeof(fd_set));
if (select(FD_SETSIZE, &rds, NULL, NULL, NULL) < 0)
{
perror("Select");
exit(1);
}
callexec(passive, rds);
}
}
int set_up_socket(short port)
{
long flags;
int sd, size;
struct sockaddr_in sin;
sd = Socket(AF_INET, SOCK_STREAM, 0);
memset(&sin, 0, sizeof(sin));
sin.sin_port = htons(port);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
Bind(sd, (struct sockaddr *) &sin, sizeof(sin));
Listen(sd, 5);
if ((flags = fcntl(sd, F_GETFL, 0)) < 0)
{
perror("Get flags");
exit(1);
}
if (fcntl(sd, F_SETFL, flags | O_NONBLOCK) < 0)
{
perror("Set flags");
exit(1);
}
return sd;
}
void callexec(int *passive, fd_set rds)
{
int i, j, sock;
int active, size;
char actives[10];
struct sockaddr_in cli;
socklen_t len;
pid_t pid;
for (i = 0; i < PASSIVE_MAX; i++)
{
if (FD_ISSET(passive[i], &rds))
{
if ((active = accept(passive[i], (struct sockaddr *) &cli,
(socklen_t *) &len)) < 0)
{
continue; /** Something bad happened to passive socket **/
}
}
else continue; /** passive[i] has no clients **/
pid = Fork();
if (pid > 0) /*** Parent ***/
{
Close(active);
}
else /**** Child ****/
{
for (j = 0; j < PASSIVE_MAX; j++)
Close(passive[j]);
sprintf(actives,"%d", active);
switch (passive[i])
{
case 3: if (execl("echos","echos", actives, NULL) < 0)
{
perror("Exec echos");
exit(1);
};
case 4: if (execl("times2","times2", actives, NULL) < 0)
{
perror("Exec times2");
exit(1);
};
}
}
}
}
void reaper(int signum)
{
pid_t kid;
int status;
while ((kid = waitpid(-1, &status, WNOHANG)) > 0) ;
siglongjmp(env, 1);
}
#include "funcs.h" /** Echo client for super server **/
int active;
#define MAXBUF 256
main()
{
struct sockaddr_in sin;
char s[MAXBUF];
struct sigaction sa;
void handler(int), term_handler(int);
Sigfillset(&sa.sa_mask);
sa.sa_handler = handler;
sa.sa_flags = 0;
Sigaction(SIGPIPE, &sa, NULL);
sa.sa_handler = term_handler;
Sigaction(SIGQUIT, &sa, NULL);
Sigaction(SIGINT, &sa, NULL);
active = Socket(PF_INET, SOCK_STREAM, 0);
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_port = htons(3071);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("153.18.17.12");
Connect(active, (struct sockaddr *) &sin, sizeof(sin));
while(printf("Enter string: "), fgets(s, MAXBUF, stdin),
strncmp(s,"quit", 4))
{
writen(active,s, MAXBUF);
memset(s, 0, MAXBUF);
readn(active, s, MAXBUF);
printf("From server: %s\n", s);
}
writen(active, "quit", 4);
Close(active);
}
/**************************** SIGPIPE handler *****************************/
void handler(int signum)
{
writen(active, "quit", 4);
printf("Server died\n");
Close(active);
exit(0);
}
/************************* Terminal signal handler ************************/
void term_handler(int signum)
{
writen(active, "quit", 4);
Close(active);
exit(0);
}
/****************** Incremental Read/Write Code ***********************/
/****************** Works on fixed-length packets.***********************/
int readn(int fd, char *buf, int bytes)
{
int nleft;
int nread;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nread = read(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
else if (nread == 0)
break; /**** EOF! ****/
nleft -= nread;
mover += nread;
}
return (bytes - nleft);
}
int writen(int fd, char *buf, int bytes)
{
int nleft;
int nwritten;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nwritten = write(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
nleft -= nwritten;
mover += nwritten;
}
return bytes;
}
#include "funcs.h" /********** This is the echo server. *********/
/********** VERY "bare bones". *********/
#define MAXBUF 256
int active;
sigjmp_buf env;
main(int argc, char **argv)
{
int readclient(int active, char *buffer, int buffer_size);
int active;
char buf[MAXBUF];
active = atoi(argv[1]);
while(alarm(45), memset(buf, 0, MAXBUF), readn(active, buf, MAXBUF),
strncmp(buf, "quit", 4))
{
alarm(0);
writen(active, buf, MAXBUF) ;
}
}
/****************** Incremental Read/Write Code ***********************/
/****************** Works on fixed-length packets.***********************/
int readn(int fd, char *buf, int bytes)
{
int nleft;
int nread;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nread = read(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
else if (nread == 0)
break; /**** EOF! ****/
nleft -= nread;
mover += nread;
}
return (bytes - nleft);
}
int writen(int fd, char *buf, int bytes)
{
int nleft;
int nwritten;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nwritten = write(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
nleft -= nwritten;
mover += nwritten;
}
return bytes;
}
#include "funcs.h" /**** Time client for superserver ****/
#define MAXBUF 256
main()
{
struct sockaddr_in sin;
char s[256];
struct sigaction sa;
void handler(void), set_no_linger(void), term_handler(void);
int active;
active = socket(PF_INET, SOCK_STREAM, 0);
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_port = htons(3072);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("153.18.17.12");
Connect(active, (struct sockaddr *) &sin, sizeof(sin));
memset(s, 0, MAXBUF);
readn(active, s, MAXBUF);
printf("Time is %s", s);
}
/****************** Incremental Read/Write Code ***********************/
/****************** Works on fixed-length packets.***********************/
int readn(int fd, char *buf, int bytes)
{
int nleft;
int nread;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nread = read(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
else if (nread == 0)
break; /**** EOF! ****/
nleft -= nread;
mover += nread;
}
return (bytes - nleft);
}
#include <time.h> /****** Time server for superserver ******/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
main(int argc, char **argv)
{
int active;
char *timeptr;
time_t now;
active = atoi(argv[1]);
now = time(NULL);
timeptr = ctime(&now);
writen(active, timeptr, strlen(timeptr)) ;
}
int writen(int fd, char *buf, int bytes)
{
int nleft;
int nwritten;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nwritten = write(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
nleft -= nwritten;
mover += nwritten;
}
return bytes;
}
/********************** Sessions with Superserver ********************/
$ supers&
[1] 6491
$ echoc ###### Echo client talks to echo server.
Enter string: hello
From server: hello
Enter string: what
From server: what
Enter string: quit
$ timec ###### Time client talks to time server.
Time is Wed Feb 24 23:18:31 1999
$ echoc ###### New echo client.
Enter string: when
From server: when
Enter string: ###### Suspended this echo client with CTRL-Z
[2] + Stopped echoc
$ echoc ###### A second echo client.
Enter string: when
From server: when
Enter string: why
From server: why
Enter string: quit
$ fg ###### Bring back old echo client.
echoc
what
Server died ###### Echo server timed echo client out.
$ timec ###### New time client.