/****************************************** * Filename : multi.c * Purpose : handles data from up to three sockets and relays to others * could easily be expanded * Author : Simon Amor (simon@leaky.org) * * Warning : This code is not fully functional - it's also not my usual * coding style. Converting this to a set of functions is left * as an exercise to the reader ;-) ***/ /* * WARNING: THIS CODE IS ONLY PARTIALLY FUNCTIONAL */ #include /* for EXIT_FAILURE and EXIT_SUCCESS */ #include #define TRUE 1 #define FALSE 0 /* network functions */ #include #include #include /* FD_SET, FD_ISSET, FD_ZERO macros */ #include int main() { int opt=TRUE; int master_socket; struct sockaddr_in address; int addrlen; int new_socket; int client_socket[3]; int max_clients=3; int activity, loop, loop2, valread; char buffer[1025]; /* data buffer of 1K */ fd_set readfds; char *message="Data-relay v0.1 (C)1996 Simon Amor \n\r"; /* initialise all client_socket[] to 0 so not checked */ for (loop=0; loop < max_clients; loop++) { client_socket[loop] = 0; } /* create the master socket and check it worked */ if ((master_socket = socket(AF_INET,SOCK_STREAM,0))==0) { /* if socket failed then display error and exit */ perror("Create master_socket"); exit(EXIT_FAILURE); } /* set master socket to allow multiple connections */ if (setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt))<0) { perror("setsockopt"); exit(EXIT_FAILURE); } /* type of socket created */ address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; /* 7000 is the port to use for connections */ address.sin_port = htons(7000); /* bind the socket to port 7000 */ if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0) { /* if bind failed then display error message and exit */ perror("bind"); exit(EXIT_FAILURE); } /* try to specify maximum of 3 pending connections for the master socket */ if (listen(master_socket, 3)<0) { /* if listen failed then display error and exit */ perror("listen"); exit(EXIT_FAILURE); } while (1==1) { FD_ZERO(&readfds); /* reason we say max_clients+3 is stdin,stdout,stderr take up the first * couple of descriptors and we might as well allow a couple of extra. * If your program opens files at all you will want to allow enough extra. * Another option is to specify the maximum your operating system allows. */ /* setup which sockets to listen on */ FD_SET(master_socket, &readfds); for (loop=0; loop 0) { FD_SET(client_socket[loop], &readfds); } } /* wait for connection, forever if we have to */ activity=select(max_clients+3, &readfds, NULL, NULL, NULL); if ((activity < 0) && (errno!=EINTR)) { /* there was an error with select() */ } if (FD_ISSET(master_socket, &readfds)) { /* Open the new socket as 'new_socket' */ addrlen=sizeof(address); if ((new_socket = accept(master_socket, (struct sockaddr *)&address, &addrlen))<0) { /* if accept failed to return a socket descriptor, display error and exit */ perror("accept"); exit(EXIT_FAILURE); } /* inform user of socket number - used in send and receive commands */ printf("New socket is fd %d\n",new_socket); /* transmit message to new connection */ if (send(new_socket, message, strlen(message), 0) != strlen(message)) { /* if send failed to send all the message, display error and exit */ perror("send"); } puts("Welcome message sent successfully"); /* add new socket to list of sockets */ for (loop=0; loop