diff --git a/README.md b/README.md index f36fc4d..dcb0641 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # :white_check_mark: EXAM (project 2020-2022) Exams of the new graph. Subjects are in the folder of each exercises, along with a solution and a test file. -At the same time, I have presented the code as a sample for solving each of the functions.if you find any bug, write to "issues". -## :white_check_mark: Exam Rank 02 -Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-02) - - +At the same time, I have presented the code as a sample for solving each of the functions.if you find any bug, write to "issues". +## :white_check_mark: Exam Rank 02 +Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-02) + + | Title | Description | Allowed functions | level of difficulty | |:-----:|-------------|-------------------|:-------------------:| | ft_printf | Write a function named `ft_printf` that will mimic the real printf | malloc, free, write, va_start, va_arg, va_copy, va_end |:star::star::star::star:| @@ -13,10 +13,10 @@ Original link to the subjects repository: [click](https://github.com/Glagan/42-e | inter |Write a program that takes two strings and displays, without doubles, the characters that appear in both strings, in the order they appear in the first one.|write|:star::star:| | union |Write a program that takes two strings and displays, without doubles, the characters that appear in either one of the strings.|write|:star:| -## :white_check_mark: Exam Rank 03 -Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-03) - - +## :white_check_mark: Exam Rank 03 +Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-03) + + | Title | Description | Allowed functions | level of difficulty | |:-----:|-------------|-------------------|:-------------------:| | micro_paint |Write a program that will read an "operation file" and print the result in the terminal (rectangle)|fopen, fread, fscanf, fclose, write, malloc, calloc, realloc, free, memset, powf, sqrtf|:star::star::star:| @@ -26,10 +26,10 @@ Original link to the subjects repository: [click](https://github.com/Glagan/42-e ![](https://github.com/markveligod/exam/raw/master/examRank03/img/micro.gif) ![](https://github.com/markveligod/exam/raw/master/examRank03/img/mini.gif) -## :white_check_mark: Exam Rank 04 -Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-04) - - +## :white_check_mark: Exam Rank 04 +Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-04) + + | Title | Description | Allowed functions | level of difficulty | |:-----:|-------------|-------------------|:-------------------:| | microshell |Write a program that will behave like executing a shell command|malloc, free, write, close, fork, waitpid, signal, kill, exit, chdir, execve, dup, dup2, pipe, strcmp, strncmp|:star::star::star::star:| @@ -53,11 +53,21 @@ To check for leaked file descriptors, use the command `lsof -c microshell`. Pay ## :white_check_mark: Exam Rank 06 -:bangbang: Attention: on the exam on the first attempt, the 8 test will fail. Just do grademe again. +:bangbang: Attention: on the exam on the first attempt, the 8 test will fail. Just do grademe again. + +Original link to the subjects repository: *in this repo* + +| Title | Description | Allowed functions | level of difficulty | +|:---------:|----------------|-------------------|:----------------:| +| mini_serv | Write a program that will listen for client to connect on a certain port on 127.0.0.1 and will let clients to speak with each other |write, close, select, socket, accept, listen, send, recv, bind, strstr, malloc, realloc, free, calloc, bzero, atoi, sprintf, strlen, exit, strcpy, strcat, memset|:star::star::star:| ## 📫 Other :bangbang: Attention: if you see any changes in the exam or there is a more elegant solution, make a pull request. -**:copyright:Authors:** - -*[Mark Veligod](https://github.com/markveligod)* +**:copyright:Authors:** + +*[Mark Veligod](https://github.com/markveligod)* + +**Helper** + +*[Belenov Andrey](https://github.com/luchikAR)* \ No newline at end of file diff --git a/examRank06/mini_serv.c b/examRank06/mini_serv.c index bab8a79..b1360c3 100644 --- a/examRank06/mini_serv.c +++ b/examRank06/mini_serv.c @@ -1,224 +1,96 @@ +#include #include -#include -#include #include #include #include -#include #include +#include +#include -typedef struct s_client -{ - int fd; - int id; - struct s_client *next; -} t_client; - -t_client *g_clients = NULL; - -int sock_fd, g_id = 0; -fd_set curr_sock, cpy_read, cpy_write; -char msg[42]; -char str[42*4096], tmp[42*4096], buf[42*4096 + 42]; - -void fatal() -{ - write(2, "Fatal error\n", strlen("Fatal error\n")); - close(sock_fd); - exit(1); -} - -int get_id(int fd) -{ - t_client *temp = g_clients; - - while (temp) - { - if (temp->fd == fd) - return (temp->id); - temp = temp->next; - } - return (-1); -} - -int get_max_fd() -{ - int max = sock_fd; - t_client *temp = g_clients; - - while (temp) - { - if (temp->fd > max) - max = temp->fd; - temp = temp->next; - } - return (max); -} - -void send_all(int fd, char *str_req) -{ - t_client *temp = g_clients; - - while (temp) - { - if (temp->fd != fd && FD_ISSET(temp->fd, &cpy_write)) - { - if (send(temp->fd, str_req, strlen(str_req), 0) < 0) - fatal(); - } - temp = temp->next; - } -} - -int add_client_to_list(int fd) -{ - t_client *temp = g_clients; - t_client *new; - - if (!(new = calloc(1, sizeof(t_client)))) - fatal(); - new->id = g_id++; - new->fd = fd; - new->next = NULL; - if (!g_clients) - { - g_clients = new; - } - else - { - while (temp->next) - temp = temp->next; - temp->next = new; - } - return (new->id); -} - -void add_client() -{ - struct sockaddr_in clientaddr; - socklen_t len = sizeof(clientaddr); - int client_fd; - - if ((client_fd = accept(sock_fd, (struct sockaddr *)&clientaddr, &len)) < 0) - fatal(); - sprintf(msg, "server: client %d just arrived\n", add_client_to_list(client_fd)); - send_all(client_fd, msg); - FD_SET(client_fd, &curr_sock); -} - -int rm_client(int fd) -{ - t_client *temp = g_clients; - t_client *del; - int id = get_id(fd); - - if (temp && temp->fd == fd) - { - g_clients = temp->next; - free(temp); - } - else - { - while(temp && temp->next && temp->next->fd != fd) - temp = temp->next; - del = temp->next; - temp->next = temp->next->next; - free(del); - } - return (id); +void fatal_error() { + write(2, "Fatal error\n", 12); + exit(1); } -void ex_msg(int fd) -{ - int i = 0; - int j = 0; +char str_buf[42*4096], read_buf[42*4096], write_buf[42*4096+42]; +int array_fd[65536], max_fd = 0, next_fd = 0; +fd_set active, ready_read, ready_write; - while (str[i]) - { - tmp[j] = str[i]; - j++; - if (str[i] == '\n') - { - sprintf(buf, "client %d: %s", get_id(fd), tmp); - send_all(fd, buf); - j = 0; - bzero(&tmp, strlen(tmp)); - bzero(&buf, strlen(buf)); - } - i++; +void send_all(int except_sock) { + int len = strlen(write_buf); + for (int sock = 0; sock <= max_fd; ++sock) { + if (FD_ISSET(sock, &ready_write) && sock != except_sock) + send(sock, write_buf, len, 0); } - bzero(&str, strlen(str)); + return ; } -int main(int ac, char **av) -{ - if (ac != 2) - { - write(2, "Wrong number of arguments\n", strlen("Wrong number of arguments\n")); +int main(int argc, char **argv) { + if (argc != 2) { + write(2, "Wrong number of arguments\n", 26); exit(1); } - - struct sockaddr_in servaddr; - uint16_t port = atoi(av[1]); - bzero(&servaddr, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(2130706433); //127.0.0.1 - servaddr.sin_port = htons(port); - - if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - fatal(); - if (bind(sock_fd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) - fatal(); - if (listen(sock_fd, 0) < 0) - fatal(); - - FD_ZERO(&curr_sock); - FD_SET(sock_fd, &curr_sock); - bzero(&tmp, sizeof(tmp)); - bzero(&buf, sizeof(buf)); - bzero(&str, sizeof(str)); - while(1) - { - cpy_write = cpy_read = curr_sock; - if (select(get_max_fd() + 1, &cpy_read, &cpy_write, NULL, NULL) < 0) + int port = atoi(argv[1]); + FD_ZERO(&active); + bzero(array_fd, sizeof(array_fd)); + + int server = socket(AF_INET, SOCK_STREAM, 0); + if (server < 0) + fatal_error(); + max_fd = server; + FD_SET(server, &active); + + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + bzero(&addr, addr_len); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = (1 << 24) | 127; + addr.sin_port = (port >> 8) | (port << 8); + + if (bind(server, &addr, addr_len) < 0) + fatal_error(); + if (listen(server, SOMAXCONN) < 0) + fatal_error(); + + while (1) { + ready_read = ready_write = active; + if (select(max_fd + 1, &ready_read, &ready_write, 0, 0) < 0) continue; - for (int fd = 0; fd <= get_max_fd(); fd++) - { - if (FD_ISSET(fd, &cpy_read)) - { - if (fd == sock_fd) - { - bzero(&msg, sizeof(msg)); - add_client(); - break; + for (int sock = 0; sock <= max_fd; ++sock) { + if (FD_ISSET(sock, &ready_read) && sock == server) { + int client = accept(server, &addr, &addr_len); + if (client < 0) + continue ; + if (client > max_fd) + max_fd = client; + array_fd[client] = next_fd++; + FD_SET(client, &active); + sprintf(write_buf, "server: client %d just arrived\n", array_fd[client]); + send_all(client); + break ; + } + if (FD_ISSET(sock, &ready_read) && sock != server) { + int read_count = recv(sock, read_buf, 42*4096, 0); + if (read_count <= 0) { + sprintf(write_buf, "server: client %d just left\n", array_fd[sock]); + send_all(sock); + FD_CLR(sock, &active); + close(sock); + break ; } - else - { - int ret_recv = 1000; - while (ret_recv == 1000 || str[strlen(str) - 1] != '\n') - { - ret_recv = recv(fd, str + strlen(str), 1000, 0); - if (ret_recv <= 0) - break ; - } - if (ret_recv <= 0) - { - bzero(&msg, sizeof(msg)); - sprintf(msg, "server: client %d just left\n", rm_client(fd)); - send_all(fd, msg); - FD_CLR(fd, &curr_sock); - close(fd); - break; - } - else - { - ex_msg(fd); + else { + for (int i = 0, j = 0; i < read_count; ++i, ++j) { + str_buf[j] = read_buf[i]; + if (str_buf[j] == '\n' || i == read_count - 1) { + str_buf[j] = '\0'; + sprintf(write_buf, "client %d: %s\n", array_fd[sock], str_buf); + send_all(sock); + j = -1; + } } } } - } - } - return (0); -} + return 0; +} \ No newline at end of file