169 похожих чатов

Https://Pastebin.Com/8bSEmdVu Подскажите почему код не завершается при подаче sigterm?

7 ответов

17 просмотров

Причина, по которой ваш код может завершиться неправильно при получении сигнала SIGTERM, может быть связана с использованием Accept в основном цикле. После получения сигнала SIGTERM вы устанавливаете выходной флаг в 1, но функция принятия блокируется и ожидает нового соединения. Это может привести к зависанию программы. Чтобы решить эту проблему, вы можете использовать неблокирующий подход к вызову принятия и добавить механизм разрыва цикла при получении сигнала SIGTERM. Вот модифицированная версия вашего кода с этими изменениями:

#include <iostream> #include <cstring> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <thread> #include <vector> #include <signal.h> constexpr int PORT = 5555; class msg { public: int from; int to; char text[1024]; }; volatile sig_atomic_t exitFlag = 0; // Завершение программы void signalHandler(int signum) { std::cout << "Received signal " << signum << std::endl; exitFlag = 1; } // Создаем таблицу подключенных устройств std::vector<std::tuple<int, int>> client_member; // Функция для обработки каждого клиента в отдельном потоке void handleClient(int clientSocket) { char buffer[1024]; // Запись клиента в таблицу подключенных устройств int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); std::tuple<int, int> temp{std::atoi(buffer), clientSocket}; client_member.push_back(temp); for (int i = 0; i < client_member.size(); i++) { std::cout << "id: " << std::get<0>(client_member.at(i)) << " socket: " << std::get<1>(client_member.at(i)) << std::endl; } while (!exitFlag) { // Получаем данные от клиента куда направить сообщение int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); if (bytesRead <= 0) { break; } int to = atoi(buffer); // Получаем данные от клиента само сообщение bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); if (bytesRead <= 0) { break; } buffer[bytesRead] = '\0'; // Выводим полученные данные от клиента в консоль сервера std::cout << "Received from client: " << buffer << " Client socket: " << clientSocket << std::endl; // Отправляем сообщение for (int i = 0; i < client_member.size(); i++) { if (std::get<0>(client_member.at(i)) == to) { send(std::get<1>(client_member.at(i)), buffer, strlen(buffer), 0); } } } // Удаляем отключившегося клиента for (auto it = client_member.begin(); it < client_member.end(); it++) { if (std::get<1>(*it) == clientSocket) { client_member.erase(it); } } // Закрываем сокет клиента после завершения обмена данными close(clientSocket); } int main() { // Создаем сокет сервера int serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == -1) { std::cerr << "Error creating socket\n"; return -1; } sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(PORT); serverAddr.sin_addr.s_addr = INADDR_ANY; // Привязываем сокет к адресу и порту if (bind(serverSocket, reinterpret_cast<struct sockaddr*>(&serverAddr), sizeof(serverAddr)) == -1) { std::cerr << "Error binding to port\n"; close(serverSocket); return -1; } // Слушаем входящие соединения if (listen(serverSocket, 5) == -1) { std::cerr << "Error listening on socket\n"; close(serverSocket); return -1; } std::cout << "Server listening on port: " << PORT << std::endl; std::vector<std::thread> clientThreads; signal(SIGTERM, signalHandler); while (!exitFlag) { sockaddr_in clientAddr; socklen_t clientAddrSize = sizeof(clientAddr); // Принимаем входящее соединение от клиента (non-blocking) int clientSocket = accept(serverSocket, reinterpret_cast<struct sockaddr*>(&clientAddr), &clientAddrSize); if (clientSocket == -1) { if (errno == EWOULDBLOCK || errno == EAGAIN) { // No incoming connection, continue continue; } else { std::cerr << "Error accepting connection\n"; close(serverSocket); return -1; } } // Запускаем новый поток для обработки клиента std::thread clientThread(handleClient, clientSocket); clientThreads.push_back(std::move(clientThread)); }

for (auto& thread : clientThreads) { thread.join(); // Ждем завершения всех потоков } // Закрываем сокет сервера close(serverSocket); return 0; }

нет бы поблагодарить

ÅÑGÈLØK
нет бы поблагодарить

так скинь ссылку на чат, там и скажем

Похожие вопросы

Обсуждают сегодня

я не магистр хаскеля, но разве не может лейзи тип конвертнуться в не-лейзи запросив вычисление содержимого прям при инициализации?
deadgnom32 λ madao
100
в сях есть множество как в питоне? для удаление дубликатов
Linus
25
читать файл максимально быстро? странный вопрос))
zamtmn
53
How to create an OS in C? what to study?
Linus
18
тоесть, указав return eax, сгенерируется никому ненужная инструкция mov eax,eax ?
Aiwan \ (•◡•) / _bot
24
Всем доброго вечера! Хочу поделиться своим злоключением с человеком, который, как оказалось сюда тоже скидывал свое резюме. Жаль, что я вашу группу не нашел раньше… человек ки...
Роман Ахмедзянов
4
а как бы вылезти из ИО, что то типа IO -> Ether или в какую сторону смотреть ? что то туплю
Fedor
8
Компания Elif ищет менеджера проектов, который будет заниматься поиском и ведением новых проектов. Прежде чем приступить к работе, вам нужно пройти наш недельный курс, где вы ...
Elif
5
Привет, кто может сделать юзербота с апи? Задачи: - создавать группы - создавать каналы - задавать для созданных каналов аватарку или эмоджи, имя группы - добавлять в группы...
Lencore
11
а зачем этот вопрос для удаления из чата?
Mёdkinson Medvezhkin
63
Карта сайта