#include "TCP.h" void TCPSocket::create_socket() { sockfd_ = socket(AF_INET, SOCK_STREAM, 0); if (sockfd_ == INVALID_SOCKET_VALUE) { throw std::runtime_error("Socket creation failed"); } } void TCPSocket::close_socket() { if (sockfd_ != INVALID_SOCKET_VALUE) { #ifdef _WIN32 closesocket(sockfd_); #else close(sockfd_); #endif sockfd_ = INVALID_SOCKET_VALUE; } connected_.store(false); } TCPSocket::~TCPSocket() { close_socket(); } bool TCPSocket::is_connected() const { return connected_.load(); } void TCPClient::connect(const std::string &ip, uint16_t port) { create_socket(); sockaddr_in addr{}; addr.sin_family = AF_INET; addr.sin_port = htons(port); inet_pton(AF_INET, ip.c_str(), &addr.sin_addr); if (::connect(sockfd_, (sockaddr *) &addr, sizeof(addr)) != 0) { close_socket(); throw std::runtime_error("Connection failed"); } connected_.store(true); } size_t TCPClient::send(const void *data, size_t size) { #ifdef _WIN32 auto sent = ::send(sockfd_, (const char *) data, (int) size, 0); #else auto sent = ::send(sockfd_, data, size, 0); #endif if (sent == SOCKET_ERROR) { connected_.store(false); throw std::runtime_error("Send failed"); } return static_cast(sent); } size_t TCPClient::send(const std::string &data) { #ifdef _WIN32 auto sent = ::send(sockfd_, data.c_str(), static_cast(data.size()), 0); #else auto sent = ::send(sockfd_, data.c_str(), data.size(), 0); #endif if (sent == SOCKET_ERROR) { connected_.store(false); throw std::runtime_error("Send failed"); } return static_cast(sent); } size_t TCPClient::receive(void *buffer, size_t buffer_size) { #ifdef _WIN32 auto received = ::recv(sockfd_, (char *) buffer, (int) buffer_size, 0); #else auto received = ::recv(sockfd_, buffer, buffer_size, 0); #endif if (received == 0) { connected_.store(false); return 0; } if (received == SOCKET_ERROR) { connected_.store(false); throw std::runtime_error("Receive failed"); } return static_cast(received); } void TCPServer::listen(uint16_t port, int backlog) { create_socket(); sockaddr_in addr{}; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd_, (sockaddr *) &addr, sizeof(addr)) != 0) { close_socket(); throw std::runtime_error("Bind failed"); } if (::listen(sockfd_, backlog) != 0) { close_socket(); throw std::runtime_error("Listen failed"); } } std::shared_ptr TCPServer::accept() { sockaddr_in client_addr{}; socklen_t addr_len = sizeof(client_addr); auto client_sock = ::accept(sockfd_, (sockaddr *) &client_addr, &addr_len); if (client_sock == INVALID_SOCKET_VALUE) { throw std::runtime_error("Accept failed"); } auto client = std::make_shared(); client->sockfd_ = client_sock; client->connected_.store(true); return client; } void AsyncTCPClient::start_async() { running_.store(true); recv_thread_ = std::thread([this]() { std::vector buffer(4096); while (running_.load()) { try { auto size = receive(buffer.data(), buffer.size()); if (size > 0) { std::lock_guard lock(queue_mutex_); recv_queue_.emplace(buffer.begin(), buffer.begin() + static_cast(size)); } } catch (...) { break; } } }); } bool AsyncTCPClient::try_pop(std::vector &data) { std::lock_guard lock(queue_mutex_); if (recv_queue_.empty()) return false; data = std::move(recv_queue_.front()); recv_queue_.pop(); return true; } AsyncTCPClient::~AsyncTCPClient() { running_.store(false); if (recv_thread_.joinable()) { recv_thread_.join(); } close_socket(); }