Advertisement
den4ik2003

Untitled

Dec 19th, 2022
996
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.43 KB | None | 0 0
  1. #include <arpa/inet.h>
  2. #include <fcntl.h>
  3. #include <netinet/in.h>
  4. #include <signal.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/sendfile.h>
  9. #include <sys/socket.h>
  10. #include <sys/stat.h>
  11. #include <unistd.h>
  12.  
  13. sig_atomic_t need_to_exit = 0;
  14. sig_atomic_t have_request = 0;
  15.  
  16. void handle_sigterm(int signal)
  17. {
  18.     need_to_exit = 1;
  19.     if (!have_request) {
  20.         _exit(0);
  21.     }
  22. }
  23.  
  24. void handle_sigint(int signal)
  25. {
  26.     need_to_exit = 1;
  27.     if (!have_request) {
  28.         _exit(0);
  29.     }
  30. }
  31.  
  32. void define_sig(struct sigaction* my_sig, void* handle_sig, int signum)
  33. {
  34.     my_sig->sa_handler = handle_sig;
  35.     my_sig->sa_flags = SA_RESTART;
  36.     sigaction(signum, my_sig, NULL);
  37. }
  38.  
  39. void addToEnd(char* str1, char* str2)
  40. {
  41.     size_t str1_sz = strlen(str1);
  42.     size_t str2_sz = strlen(str2);
  43.     size_t i = 0;
  44.     for (; i < str2_sz; ++i) {
  45.         str1[str1_sz + i] = str2[i];
  46.     }
  47.     str1[str1_sz + i] = '\0';
  48. }
  49.  
  50. //создание сервера
  51. const char* localhost = "127.0.0.1";
  52.  
  53. int initialize_server(
  54.     struct sockaddr_in* serv_addr,
  55.     const char* serv_adr,
  56.     char* port_num)
  57. {
  58.     memset(serv_addr, 0, sizeof(serv_addr));
  59.     serv_addr->sin_family = AF_INET;
  60.     serv_addr->sin_addr.s_addr = inet_addr(serv_adr);
  61.     if (serv_addr->sin_addr.s_addr == -1) {
  62.         return -1;
  63.     }
  64.     serv_addr->sin_port = htons(atoi(port_num));
  65.     return 0;
  66. }
  67.  
  68. //для работы с 1 клиентом
  69. void work_with_client(int connection_fd, char* catalog_path)
  70. {
  71.     const int buf_size = 4096;
  72.     //читаем запрос от клиента
  73.     char request[buf_size];
  74.     int request_size = read(connection_fd, request, sizeof(request));
  75.     if (request_size < 15) {
  76.         perror("incorrect_request");
  77.         return;
  78.     }
  79.  
  80.     //ищем и создаем имя файла
  81.     int catalog_path_len = strlen(catalog_path) + 1;
  82.     char file_name[buf_size + catalog_path_len];
  83.     addToEnd(file_name, catalog_path);
  84.     addToEnd(file_name, "/");
  85.     int ind = 0;
  86.  
  87.     while (request[4 + ind] != ' ') {
  88.         file_name[catalog_path_len + ind] = request[4 + ind];
  89.         ind++;
  90.     }
  91.     file_name[catalog_path_len + ind] = '\0';
  92.  
  93.     //узнаем, существует ли
  94.     if (access(file_name, F_OK) != 0) {
  95.         dprintf(
  96.             connection_fd,
  97.             "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
  98.         return;
  99.     }
  100.     //а вдруг существует, но читать нельзя
  101.     else if (access(file_name, R_OK) != 0) {
  102.         dprintf(
  103.             connection_fd,
  104.             "HTTP/1.1 403 Forbidden\r\nContent-Length: 0\r\n\r\n");
  105.         return;
  106.     }
  107.     //значит существует и читаем
  108.     //узнаем, кто этот файл по жизни
  109.     int file_fd = open(file_name, O_RDONLY);
  110.     struct stat file_stat;
  111.     int is_file_ok = lstat(file_name, &file_stat);
  112.  
  113.     if (file_fd != -1 && is_file_ok != -1) {
  114.         dprintf(
  115.             connection_fd,
  116.             "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n",
  117.             file_stat.st_size);
  118.  
  119.         sendfile(connection_fd, file_fd, 0, file_stat.st_size);
  120.     }
  121. }
  122.  
  123. //организация работы с клиентами
  124. int process_clients(int socket_fd, char* catalog_path)
  125. {
  126.     while (!need_to_exit) {
  127.         struct sockaddr_in client;
  128.         socklen_t client_size = sizeof(struct sockaddr_in);
  129.         int connection_fd =
  130.             accept(socket_fd, (struct sockaddr*)&client, &client_size);
  131.  
  132.         if (connection_fd == -1) {
  133.             perror("connection_fail");
  134.             return 1;
  135.         }
  136.         have_request = 1;
  137.         work_with_client(connection_fd, catalog_path);
  138.  
  139.         shutdown(connection_fd, SHUT_RDWR);
  140.         close(connection_fd);
  141.         have_request = 0;
  142.     }
  143. }
  144.  
  145. //функция работы сервера
  146. int server_function(char* port_num, char* catalog_path)
  147. {
  148.     int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  149.     if (socket_fd == -1) {
  150.         perror("create_socket_fail");
  151.         return 1;
  152.     }
  153.  
  154.     //инициализируем сокет
  155.     struct sockaddr_in serv;
  156.     int is_all_successful = initialize_server(&serv, localhost, port_num);
  157.     if (is_all_successful == -1) {
  158.         perror("initialize_server_fail");
  159.         return 1;
  160.     }
  161.  
  162.     //привязываем дескриптор и сокет
  163.     is_all_successful = bind(socket_fd, (struct sockaddr*)&serv, sizeof(serv));
  164.     if (is_all_successful == -1) {
  165.         perror("bind_server_fail");
  166.         return 1;
  167.     }
  168.  
  169.     //создаем очередь
  170.     is_all_successful = listen(socket_fd, SOMAXCONN);
  171.     if (is_all_successful == -1) {
  172.         perror("listen_fail");
  173.         return 1;
  174.     }
  175.  
  176.     //работа с клиентами
  177.     if (process_clients(socket_fd, catalog_path)) {
  178.         return 1;
  179.     }
  180.  
  181.     //закрываем сокет
  182.     shutdown(socket_fd, SHUT_RDWR);
  183.     close(socket_fd);
  184.  
  185.     return 0;
  186. }
  187. ////////////////////
  188.  
  189. int main(int argc, char** argv)
  190. {
  191.     //переопределяем действие сигналов
  192.     struct sigaction my_sigterm;
  193.     define_sig(&my_sigterm, handle_sigterm, SIGTERM);
  194.  
  195.     struct sigaction my_sigint;
  196.     define_sig(&my_sigint, handle_sigint, SIGINT);
  197.  
  198.     //запускаем сервер и работаем с клиентом
  199.     server_function(argv[1], argv[2]);
  200.  
  201.     return 0;
  202. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement