#include "Network/Server/Server.h" #include #include #include #include #include "Metrics/Host.h" namespace Network { Server::Server(uint16_t port, Model::HostRegistry ®istry) : port_(port), registry_(registry), running_(false) { sockfd_ = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd_ < 0) throw std::runtime_error("Failed to create UDP socket"); sockaddr_in addr{}; addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(port_); if (bind(sockfd_, reinterpret_cast(&addr), sizeof(addr)) < 0) { throw std::runtime_error("Failed to bind UDP socket"); } } Server::~Server() { stop(); close(sockfd_); } void Server::start() { running_ = true; serverThread_ = std::thread(&Server::run, this); } void Server::stop() { running_ = false; if (serverThread_.joinable()) serverThread_.join(); } void Server::run() { constexpr size_t BUF_SIZE = 4096; uint8_t buffer[BUF_SIZE]; while (running_) { fd_set readfds; FD_ZERO(&readfds); FD_SET(sockfd_, &readfds); timeval tv{}; tv.tv_sec = 0; tv.tv_usec = 500 * 1000; // 500 ms int ret = select(sockfd_ + 1, &readfds, nullptr, nullptr, &tv); if (ret < 0) { if (errno == EINTR) continue; perror("select"); break; } if (ret == 0) { // timeout — просто проверяем running_ continue; } if (FD_ISSET(sockfd_, &readfds)) { sockaddr_in clientAddr{}; socklen_t addrLen = sizeof(clientAddr); ssize_t len = recvfrom( sockfd_, buffer, BUF_SIZE, 0, reinterpret_cast(&clientAddr), &addrLen); if (len <= 0) continue; try { std::vector data(buffer, buffer + len); auto metrics = Metrics::Host::deserialize(data); registry_.update(metrics.hostname, metrics); } catch (const std::exception &e) { std::cerr << "UDP parse error: " << e.what() << std::endl; } } } } } // namespace Network