#include #include #include #include #include #include #include #include // accept // atoi // bind // bzero // calloc // close // exit // free // listen // malloc // memset // realloc // recv // select // send // socket // sprintf // strcat // strcpy // strlen // strstr // write #define BUFSIZE 100 typedef struct s_client { int fd; int id; char *msg; struct s_client *next; } t_client; void error(char *msg) { write(2, msg, strlen(msg)); exit(1); } int extract_message(char **buf, char **msg) { char *newbuf; int i; *msg = 0; if (*buf == 0) return (0); i = 0; while ((*buf)[i]) { if ((*buf)[i] == '\n') { newbuf = calloc(1, sizeof(*newbuf) * (strlen(*buf + i + 1) + 1)); if (newbuf == 0) return (-1); strcpy(newbuf, *buf + i + 1); *msg = *buf; (*msg)[i + 1] = 0; *buf = newbuf; return (1); } i++; } return (0); } char *str_join(char *buf, char *add) { char *newbuf; int len; if (buf == 0) len = 0; else len = strlen(buf); newbuf = malloc(sizeof(*newbuf) * (len + strlen(add) + 1)); if (newbuf == 0) return (0); newbuf[0] = 0; if (buf != 0) strcat(newbuf, buf); free(buf); strcat(newbuf, add); return (newbuf); } void add_client(t_client **first_client, int fd, int id) { t_client *new_client; t_client *client; new_client = calloc(1, sizeof(*new_client)); if (!new_client) error("Fatal error\n"); new_client->fd = fd; new_client->id = id; new_client->next = NULL; if (!(*first_client)) *first_client = new_client; else { client = *first_client; while (client->next) client = client->next; client->next = new_client; } } void broadcast(char *buf, fd_set *set, int maxfd, int client_fd) { for(int fd = 0; fd <= maxfd; ++fd) { if (fd == client_fd) continue; if (FD_ISSET(fd, set)) send(fd, buf, strlen(buf), 0); } } // debug void print_clients(t_client *client) { printf("clients:"); while(client) { printf("[%i - %i]", client->id, client->fd); client = client->next; } printf("\n"); } int main(int ac, char **av) { int sockfd; int client_fd; int maxfd; int id; struct sockaddr_in servaddr; fd_set read_set; fd_set write_set; t_client *client; t_client *first_client; char buf[BUFSIZE]; if (ac != 2) error("Wrong number of arguments\n"); client = NULL; id = 0; first_client = client; // socket create and verification sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) error("Fatal error\n"); bzero(&servaddr, sizeof(servaddr)); // assign IP, PORT servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(2130706433); //127.0.0.1 servaddr.sin_port = htons(atoi(av[1])); // Binding newly created socket to given IP and verification if ((bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr))) == -1) error("Fatal error\n"); if (listen(sockfd, 10) == -1) error("Fatal error\n"); while(1) { //print_clients(first_client); maxfd = sockfd; FD_ZERO(&read_set); FD_ZERO(&write_set); FD_SET(sockfd, &read_set); client = first_client; while(client) { FD_SET(client->fd, &read_set); FD_SET(client->fd, &write_set); if (client->fd > maxfd) maxfd = client_fd; client = client->next; } select(maxfd + 1, &read_set, NULL, NULL, NULL); if (FD_ISSET(sockfd, &read_set)) { client_fd = accept(sockfd, NULL, NULL); add_client(&first_client, client_fd, id); sprintf(buf, "server: client %d just arrived\n", id); broadcast(buf, &write_set, maxfd, client_fd) { id++; } } return (0); }