// #include #include #include #include #include #include #include #include typedef struct s_clients { int id; char msg[1024]; } t_clients; // so we just have a table of clients, no need to worry about linked lists, yea sounds good to me t_clients clients[1024]; // 1024 otherwise would have to change FD_SETSIZE and why bother fd_set readfds, writefds, active; int fd_Max = 0; int id_Next = 0; char bufread[120000]; char bufwrite[120000]; void ft_error(char *str) { // 2 is stderr i guess if (str) write(2, str, strlen(str)); else write(2, "Fatal error", strlen("Fatal error")); write(2, "\n", 1); exit(1); } // not is the fd that send the message meaning you should not send that message to that fd void send_to_all(int not) { for(int i = 0; i <= fd_Max; i++) { // have to check cuz we use an array not a linked list if (FD_ISSET(i, &writefds) && i != not) send(i, bufwrite, strlen(bufwrite), 0); // man send explains things well } } int main(int ac, char **av) { if (ac != 2) ft_error("Wrong number of arguments"); // just like in main.c // all this is explained in the man socket, cool int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) ft_error(NULL); // like bzeroing i guess but for the struct fd_set, yea it clears the set, none are active FD_ZERO(&active); // i think this gets all the contents of the structs as well ? yes cuz it's an array not a linked list so easy to bzero bzero(&clients, sizeof(clients)); fd_Max = sockfd; // not sure what that does, none of this is in main.c FD_SET(sockfd, &active); // we add sockfd to active, ok cool struct sockaddr_in servaddr; // like in main.c socklen_t len; // not in main.c, i mean it kinda is but i prefer doing it this way, not even that important bzero(&servaddr, sizeof(servaddr)); // in main.c servaddr.sin_family = AF_INET; // like main.c servaddr.sin_addr.s_addr = htonl(2130706433); // like main.c servaddr.sin_port = htons(atoi(av[1])); // slightly different than main.c cuz have to get the right port // just like main.c, we bind and listen, normal stuff that requres specific numbers if ((bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr))) < 0) ft_error(NULL); if (listen(sockfd, 10) < 0) ft_error(NULL); // no longer like main.c while(1) { readfds = active; writefds = active; // so like if it didn't add a new one? it continues? yea idk something about making sure select has happened if (select(fd_Max + 1, &readfds, &writefds, NULL, NULL) < 0) continue; // we cycle through all the FDs we've assigned at one point so far (they may not all be active) for (int fd_i = 0; fd_i <= fd_Max; fd_i++) { // for each one we check if it's set, and check if is or isn't sockfd // ohhh this is if a client just arrived if (FD_ISSET(fd_i, &readfds) && fd_i == sockfd) { // try to accept a new connection int connfd = accept(sockfd, (struct sockaddr*)&servaddr, &len); // more or less in main.c if (connfd < 0) continue; // non blocking but this one didn't work // reset fd_max fd_Max = connfd > fd_Max ? connfd : fd_Max; // whichever is larger is the new max clients[connfd].id = id_Next++; // we add the new client FD_SET(connfd, &active); // add it to the list sprintf(bufwrite, "server: client %d just arrived\n", clients[connfd].id); // create message to send out send_to_all(connfd); break; } // things other than a new connection i guess if (FD_ISSET(fd_i, &readfds) && fd_i != sockfd) { // 65536 is just a big number i think int res = recv(fd_i, bufread, 65536, 0); // similar to send, also see man recv, it's good // something happened to a client so we tell the others this one is gone and handle clears and prevent leaks and such if (res <= 0) // -1 is error and 0 is end of file { sprintf(bufwrite, "server: client %d just left\n", clients[fd_i].id); send_to_all(fd_i); FD_CLR(fd_i, &active); close(fd_i); break; } else { // we read the whole message we just received and then send it out for(int i = 0, j = strlen(clients[fd_i].msg); i < res; i++, j++) { clients[fd_i].msg[j] = bufread[i]; if (clients[fd_i].msg[j] == '\n') { clients[fd_i].msg[j] = '\0'; sprintf(bufwrite, "client %d: %s\n", clients[fd_i].id, clients[fd_i].msg); send_to_all(fd_i); bzero(clients[fd_i].msg, strlen(clients[fd_i].msg)); j = -1; // becomes 0 right after this at the end of the loop, i think } } break; } } } } return (0); }