//#include //#include #include #include #include #include #include #include //sprintf // accept // atoi // bind // bzero // calloc // close // exit // free // listen // malloc // memset // realloc // recv // select // send // socket // sprintf // strcat // strcpy // strlen // strstr // write #define BUFSIZE 42000 void error(char *str) { write(2, str, strlen(str)); exit(1); } int init_socket(struct sockaddr_in *addr, int len, int port) { int server_fd; if ( (server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) error("Fatal error2\n"); bzero(addr, len); addr->sin_family = AF_INET; addr->sin_addr.s_addr = htonl(2130706433); //127.0.0.1 addr->sin_port = htons(port); if (bind(server_fd, (const struct sockaddr *)addr, len) == -1) error("Fatal error3\n"); if (listen(server_fd, 10) == -1) error("Fatal error4\n"); return server_fd; } void broadcast(char *buf, fd_set *set, int max_fd, int server_fd, int sender_fd) { for(int i = 0; i <= max_fd; ++i) { if (i == server_fd) continue; if (i == sender_fd) continue; if (FD_ISSET(i, set)) send(i, buf, strlen(buf), 0); } } int main(int ac, char **av) { int server_fd; int client_fd; int client_id; int port; int max_fd; int ret; int clients[FD_SETSIZE]; char buf[BUFSIZE]; char tmpbuf[BUFSIZE]; char msg[BUFSIZE]; struct sockaddr_in addr; socklen_t addr_len; fd_set fdset; fd_set rdset; if (ac != 2) error("Wrong number of arguments\n"); if ( (port = atoi(av[1])) == -1) error("Fatal error1\n"); addr_len = sizeof(addr); server_fd = init_socket(&addr, addr_len, port); FD_ZERO(&fdset); FD_SET(server_fd, &fdset); max_fd = server_fd; client_id = 0; /* */ while (1) { rdset = fdset; select(max_fd + 1, &rdset, NULL, NULL, NULL); // new connection if (FD_ISSET(server_fd, &rdset)) { client_fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); FD_SET(client_fd, &fdset); clients[client_fd] = client_id; if (client_fd > max_fd) max_fd = client_fd; sprintf(msg, "server: client %d just arrived\n", client_id); broadcast(msg, &fdset, max_fd, server_fd, client_fd); client_id++; } // new message client_fd = 0; while(client_fd <= max_fd) { ret = 1; if (FD_ISSET(client_fd, &rdset)) { bzero(buf, BUFSIZE); ret = recv(client_fd, buf, BUFSIZE, 0); if (ret == 0) { sprintf(msg, "server: client %d just left\n", clients[client_fd]); broadcast(msg, &fdset, max_fd, server_fd, client_fd); FD_CLR(client_fd, &fdset); } else if (ret > 0) { for(int i = 0, j = 0; buf[i] != '\n'; ++i, ++j) { tmpbuf[j] = buf[i]; if (buf[i] == '\n') { tmpbuf[j] = '\0'; sprintf(msg, "client %d: %s\n", clients[client_fd], tmpbuf); broadcast(msg, &fdset, max_fd, server_fd, client_fd); bzero(tmpbuf, strlen(tmpbuf)); j = -1; } } } } client_fd++; } } return (0); }