#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum { AVAILABLE = -1, DEFAULT_PORT = 2000, MAXCLIENTS = 20 }; void main_loop (int sockfd); int init_network (int port); int connection (int sockfd); void process_msg (int whichfd); void shutdown_socket (int whichfd); static int clients[MAXCLIENTS]; int main (int argc, char* argv[]) { int i; int port; int sockfd; if (argc > 1) port = atoi (argv[1]); else port = DEFAULT_PORT; for (i = 0; i < MAXCLIENTS; i++) clients[i] = AVAILABLE; if ((sockfd = init_network (port)) < 0) { fprintf (stderr, "init_network: Failure\n"); return 3; } main_loop (sockfd); return 0; } int init_network (int port) { struct sockaddr_in saddr; int opt = 1; int sockfd; if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return -1; } memset ((char *) &saddr, 0, sizeof (saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl (INADDR_ANY); saddr.sin_port = htons (port); if (bind (sockfd, (struct sockaddr *) &saddr, sizeof (saddr)) < 0) { perror ("bind"); return -1; } if (listen (sockfd, 5) < 0) { perror ("listen"); return -1; } return sockfd; } /* * Handles new connections */ int connection (int sockfd) { struct sockaddr_in newuser; int newuser_len; int avail; for (avail = 0; avail < MAXCLIENTS; avail++) { if (clients[avail] == AVAILABLE) break; } if (avail >= MAXCLIENTS) { return -1; } newuser_len = sizeof (newuser); clients[avail] = accept (sockfd, (struct sockaddr *) &newuser, &newuser_len); if (clients[avail] < 0) { perror("accept"); clients[avail] = AVAILABLE; return -1; } return avail; } void main_loop (int sockfd) { int dnum; int maxfd; struct timeval timeout; fd_set input_set; fd_set output_set; int waitseconds = 10; while (1) { FD_ZERO (&output_set); FD_ZERO (&input_set); FD_SET (sockfd, &input_set); maxfd = sockfd; /* Loop through the clients looking for input */ for (dnum = 0; dnum < MAXCLIENTS; dnum++) { if (clients[dnum] != AVAILABLE) { FD_SET(clients[dnum], &input_set); if (clients[dnum] > maxfd) maxfd = clients[dnum]; } } timeout.tv_sec = waitseconds; timeout.tv_usec = 0; dnum = select (maxfd + 1, &input_set, &output_set, 0, &timeout); if (dnum < 0) { perror("select"); dnum = 0; } if (dnum) { /* select says we have something */ if (FD_ISSET (sockfd, &input_set)) { connection (sockfd); /* new connection pending */ } for (dnum = 0; dnum < MAXCLIENTS; dnum++) { if (clients[dnum] != AVAILABLE) { if (FD_ISSET (clients[dnum], &input_set)) process_msg (dnum); } } } } } /* This reads anything off the respective fd. */ void process_msg (int whichfd) { int numread; int numwritten; char buffer[1024]; int dnum; int offset = 0; while (1) { numread = read (clients[whichfd], buffer + offset, sizeof (buffer) - offset); if (numread < 0) perror ("read"); if (numread <= 0) { shutdown_socket (whichfd); return; } offset += numread; if (buffer[offset - 1] == '\n') break; } for (dnum = 0; dnum < MAXCLIENTS; dnum++) if (clients[dnum] != AVAILABLE) { numwritten = write (clients[dnum], buffer, offset); if (numwritten <= 0) { perror ("write"); shutdown_socket(dnum); } } } /* This shuts down the respective socket */ void shutdown_socket (int whichfd) { shutdown (clients[whichfd], 2); close (clients[whichfd]); clients[whichfd] = AVAILABLE; }