#include #include #include #include #include #include #include #include #include #include #define _GNU_SOURCE #include #define BUF_SIZE 512 #define MAX_FDS 1024 int *all_fds; int handle_client(void *arg) { int myfd = (int) arg; /* the file descriptor associated with this client */ char data[BUF_SIZE]; /* the buffer we use to store the data we receive from the client */ int nbytes; /* number of bytes we read from the socket */ int i; /* zero out the buffer */ memset(data, '\0', BUF_SIZE); while (1) { /* this will block until we receive some data */ nbytes = read(myfd, data, BUF_SIZE-1); if (nbytes == -1) { /* error */ perror("read"); exit(1); } else if (nbytes == 0) { /* client disconnected */ fprintf(stderr, "[%d] socket %d closed connection\n", getpid(), myfd); /* release the file descriptor */ all_fds[myfd] = -1; /* terminate the child */ exit(0); } else { /* print the message */ data[nbytes - 1] = '\0'; printf("[%d] - %s\n", getpid(), data); /* transmit the message to everyone */ for (i = 0; i < MAX_FDS; i++) { if (all_fds[i] != myfd && all_fds[i] != -1) { if (write(all_fds[i], data, nbytes) == -1) fprintf(stderr, "write error i is %d, all_fds[i] is %d\n", i, all_fds[i]); } } } } return 0; } int main(int argc, char *argv[]) { int listen_fd; /* File descriptor for listening */ struct sockaddr_in addr; /* Struct that holds server address */ struct sockaddr_in cli_addr; /* Struct that holds client address */ socklen_t cli_addrlen = sizeof(cli_addr); int client_fd, shmid, i; key_t key; key = ftok("fork-server",'R'); shmid = shmget(key, MAX_FDS * sizeof(int), 0666 | IPC_CREAT); all_fds = (int *)shmat(shmid, (void *)0, 0); /* initialize all_fds with -1 */ for (i = 0; i < MAX_FDS; i++) all_fds[i] = -1; /* initialize the struct with the server address */ addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(1234); memset(addr.sin_zero, '\0', sizeof(addr.sin_zero)); /* Create the listening socket */ listen_fd = socket(PF_INET, SOCK_STREAM, 0); /* Assign server address to the socket */ bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)); /* Start listening for connections */ listen(listen_fd, 10); for(;;) { /* accept blocks until we have a new connection */ client_fd = accept(listen_fd, (struct sockaddr *)&cli_addr, &cli_addrlen); all_fds[client_fd] = client_fd; clone(handle_client, (void **) (malloc(0x10000) + 0xFFFC), CLONE_FILES, (void *)client_fd); } return 0; }