Причина, по которой ваш код может завершиться неправильно при получении сигнала 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; }
нет бы поблагодарить
так скинь ссылку на чат, там и скажем
Ага я глупая по вашему?
Обсуждают сегодня