Step 2
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
#include "Network/Server/Server.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#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<sockaddr *>(&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<sockaddr *>(&clientAddr),
|
||||
&addrLen);
|
||||
|
||||
if (len <= 0)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<uint8_t> 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
|
||||
Reference in New Issue
Block a user