#include "server.h" CTcpServer::CTcpServer(asio::io_context& io_context, const std::shared_ptr& logger) : io_context_(io_context), logger_(logger), acceptor_(io_context) { } CTcpServer::~CTcpServer() { } bool CTcpServer::Start(unsigned short port) { asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port); try { acceptor_.open(endpoint.protocol()); acceptor_.set_option(asio::socket_base::reuse_address(true)); acceptor_.bind(endpoint); acceptor_.listen(); } catch (const asio::system_error& e) { logger_->error("Failed to bind to {}: {}", endpoint.address().to_string(), e.what()); return false; } Accept(); logger_->info("Server started on port {}", port); return true; } void CTcpServer::Stop() { acceptor_.close(); std::lock_guard lock(mutex_); for (auto& [key, thread] : client_threads_) { if (thread.joinable()) { thread.join(); } } client_threads_.clear(); } void CTcpServer::handle_data(CFrameBuffer* buf) { if (buf == nullptr) { logger_->error("{} nullptr.", __FUNCTION__); return; } } void CTcpServer::Accept() { auto socket = std::make_shared(io_context_); acceptor_.async_accept(*socket, [this, socket](const asio::error_code& error) { if (!error) { auto endpoint = socket->remote_endpoint(); std::string client_key = endpoint.address().to_string() + ":" + std::to_string(endpoint.port()); logger_->info("New connection from {}", client_key); { std::lock_guard lock(mutex_); client_map_[client_key] = std::make_shared(); } client_threads_[client_key] = std::thread(&CTcpServer::HandleClient, this, socket, client_key); } Accept(); }); } void CTcpServer::HandleClient(std::shared_ptr socket, const std::string& client_key) { try { while (true) { asio::error_code error; size_t length = socket->read_some(asio::buffer(client_map_[client_key]->tmp_buf_), error); if (error == asio::error::eof) { logger_->info("Connection closed by client: {}", client_key); break; } else if (error) { throw asio::system_error(error); } client_map_[client_key]->buffer_.push(client_map_[client_key]->tmp_buf_.data(), length); auto* frame = CTransProtocal::parse(client_map_[client_key]->buffer_); frame->id_ = client_key; if (frame) { handle_data(frame); delete frame; } // auto relen = socket->send(asio::buffer(data, length)); // logger_->info("Received data from {}, len={}, relen={}", client_key, length, relen); } } catch (std::exception& e) { logger_->error("Error with client {}: {}", client_key, e.what()); } std::lock_guard lock(mutex_); client_map_.erase(client_key); if (client_threads_.find(client_key) != client_threads_.end()) { client_threads_.at(client_key).detach(); client_threads_.erase(client_key); } }