transm/server/server.cpp

103 lines
3.2 KiB
C++
Raw Normal View History

#include "server.h"
2024-12-12 23:11:55 +08:00
CTcpServer::CTcpServer(asio::io_context& io_context, const std::shared_ptr<spdlog::logger>& logger)
: io_context_(io_context), logger_(logger), acceptor_(io_context)
{
}
CTcpServer::~CTcpServer()
{
}
2024-12-12 23:11:55 +08:00
bool CTcpServer::Start(unsigned short port)
{
2024-12-12 23:11:55 +08:00
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;
}
2024-12-12 23:11:55 +08:00
void CTcpServer::Stop()
{
2024-12-12 23:11:55 +08:00
acceptor_.close();
std::lock_guard<std::mutex> 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;
}
}
2024-12-12 23:11:55 +08:00
void CTcpServer::Accept()
{
2024-12-12 23:11:55 +08:00
auto socket = std::make_shared<asio::ip::tcp::socket>(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<std::mutex> lock(mutex_);
client_map_[client_key] = std::make_shared<ClientCache>();
}
client_threads_[client_key] = std::thread(&CTcpServer::HandleClient, this, socket, client_key);
}
Accept();
});
}
2024-12-12 23:11:55 +08:00
void CTcpServer::HandleClient(std::shared_ptr<asio::ip::tcp::socket> 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<std::mutex> 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);
}
}