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