anechka_ne_plach

Untitled

May 27th, 2022 (edited)
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.52 KB | None | 0 0
  1. 8 │ ### Problem kr09-5: kr09-5
  2. 9 │
  3. 10 │ На стандартном потоке ввода задается номер порта PORT. Программа должна слушать входящие TCP (v4)
  4. 11 │ соединения на порту PORT. Предполагается, что клиенты подключаются к серверу последовательно, то
  5. 12 │ есть не требуется взаимодействовать с несколькими клиентами одновременно.
  6. 13 │
  7. 14 │ После подключения каждый клиент посылает на сервер последовательность вещественных чисел типа float
  8. 15 │ в сетевом порядке байт. В конце последовательности клиент закрывает соединение.
  9. 16 │
  10. 17 │ Для каждого клиента вычисляется среднее арифметическое переданных чисел. Если не было передано ни
  11. 18 │ одного числа, среднее арифметическое полагается равным 0.
  12. 19 │
  13. 20 │ При получении сигнала SIGTERM сервер выводит на стандартный поток вывода сумму средних
  14. 21 │ арифметических всех полностью обработанных клиентов и завершает работу с кодом 0. Если не был
  15. 22 │ обработан ни один клиент, сумма полагается равной 0.
  16. 23 │
  17. 24 │ Хотя клиент передает числа типа float, все вычисления вести в типе double. Результат выводить с
  18. 25 │ помощью форматного преобразования %.10g.
  19. 26 │
  20. 27 │ В обработчике сигнала разрешается только устанавливать флаг.
  21.  
  22. 1 │ #include <sys/types.h>
  23. 2 │ #include <sys/socket.h>
  24. 3 │ #include <netdb.h>
  25. 4 │ #include <stdio.h>
  26. 5 │ #include <stdlib.h>
  27. 6 │ #include <netinet/in.h>
  28. 7 │ #include <netdb.h>
  29. 8 │ #include <arpa/inet.h>
  30. 9 │ #include <string.h>
  31. 10 │ #include <errno.h>
  32. 11 │ #include <sys/wait.h>
  33. 12 │ #include <signal.h>
  34. 13 │ #include <unistd.h>
  35. 14 │ #include <limits.h>
  36. 16 │ volatile sig_atomic_t term_triggered = 0;
  37. 17 │
  38. 18 │ void handler(int s) {
  39. 19 │ term_triggered = 1;
  40. 20 │ }
  41. 21 │ int main(int argc, char* argv[]) {
  42. 22 │ sigset_t sigset, empty;
  43. 23 │ sigemptyset(&sigset);
  44. 24 │ sigemptyset(&empty);
  45. 25 │ sigaddset(&sigset, SIGTERM);
  46. 26 │ sigprocmask(SIG_BLOCK, &sigset, NULL);
  47. 27 │ sigaction(SIGTERM, &(struct sigaction) { .sa_handler=handler, .sa_flags = SA_RESTART }, NULL);
  48. 28 │
  49. 29 │ // fprintf(stderr, "my_pid: %d\n", getpid());
  50. 30 │
  51. 31 │ int sfd;
  52. 32 │ if ((sfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  53. 33 │ perror("socket");
  54. 34 │ return 1;
  55. 35 │ }
  56. 36 │
  57. 37 │ int sopt = 1;
  58. 38 │ if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &sopt, sizeof(sopt)) < 0) {
  59. 39 │ close(sfd);
  60. 40 │ perror("setsockopt SO_REUSEADDR");
  61. 41 │ return 1;
  62. 42 │ }
  63. 43 │ if (setsockopt(sfd, SOL_SOCKET, SO_REUSEPORT, &sopt, sizeof(sopt)) < 0) {
  64. 44 │ close(sfd);
  65. 45 │ perror("setsockopt SO_REUSEPORT");
  66. 46 │ return 1;
  67. 47 │ }
  68. 48 │
  69. 49 │ struct sockaddr_in addr;
  70. 50 │ addr.sin_family = AF_INET;
  71. 51 │ addr.sin_port = htons(strtol(argv[1], NULL, 10));
  72. 52 │ addr.sin_addr.s_addr = INADDR_ANY;
  73. 53 │
  74. 54 │ if (bind(sfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
  75. 55 │ close(sfd);
  76. 56 │ perror("bind");
  77. 57 │ return 1;
  78. 58 │ }
  79. 59 │
  80. 60 │ if (listen(sfd, 5) < 0) {
  81. 61 │ close(sfd);
  82. 62 │ perror("listen");
  83. 63 │ return 1;
  84. 64 │ }
  85. 65 │
  86. 66 │ double total_sum = 0;
  87. 67 │ while (!term_triggered) {
  88. 68 │ struct sockaddr_in new_addr;
  89. 69 │ socklen_t new_len = sizeof(struct sockaddr_in);
  90. 70 │ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
  91. 71 │ int afd = accept(sfd, (struct sockaddr*)&new_addr, &new_len);
  92. 72 │ sigprocmask(SIG_BLOCK, &sigset, NULL);
  93. 73 │ if (afd < 0) {
  94. 74 │ if (term_triggered) break;
  95. 75 │ close(sfd);
  96. 76 │ perror("accept");
  97. 77 │ return 0;
  98. 78 │ }
  99. 79 │ if (term_triggered) {
  100. 80 │ close(afd);
  101. 81 │ break;
  102. 82 │ }
  103. 83 │ int pid = 0;
  104. 84 │ if (pid < 0) {
  105. 85 │ if (term_triggered) {
  106. 86 │ close(afd);
  107. 87 │ break;
  108. 88 │ }
  109. 89 │ perror("fork");
  110. 90 │ } else if (!pid) {
  111. 91 │ FILE* s_in = fdopen(afd, "r");
  112. 92 │
  113. 93 │ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
  114. 94 │ float cur = 0;
  115. 95 │ double cur_sum = 0;
  116. 96 │ long long cur_count = 0;
  117. 97 │ int res;
  118. 98 │ while (!term_triggered && (res = fscanf(s_in, "%f", &cur)) != EOF) {
  119. 99 │ if (res < 0) {
  120. 100 │ break;
  121. 101 │ }
  122. 102 │ cur_sum += cur;
  123. 103 │ cur_count++;
  124. 104 │ }
  125. 105 │ if (term_triggered) {
  126. 106 │ break;
  127. 107 │ }
  128. 108 │ sigprocmask(SIG_BLOCK, &sigset, NULL);
  129. 109 │ if (cur_count) {
  130. 110 │ cur_sum /= cur_count;
  131. 111 │ total_sum += cur_sum;
  132. 112 │ }
  133. 113 │ fclose(s_in);
  134. 114 │ }
  135. 115 │ close(afd);
  136. 116 │ }
  137. 117 │ close(sfd);
  138. 118 │ printf("%.10g\n", total_sum);
  139. 119 │ }
Add Comment
Please, Sign In to add comment