This commit is contained in:
2025-06-16 08:52:40 +08:00
commit e53dc4a080
23 changed files with 1725 additions and 0 deletions

156
Socket/TCP.cpp Normal file
View File

@ -0,0 +1,156 @@
#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<size_t>(sent);
}
size_t TCPClient::send(const std::string &data) {
#ifdef _WIN32
auto sent = ::send(sockfd_, data.c_str(), static_cast<int>(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<size_t>(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<size_t>(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<TCPClient> 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<TCPClient>();
client->sockfd_ = client_sock;
client->connected_.store(true);
return client;
}
void AsyncTCPClient::start_async() {
running_.store(true);
recv_thread_ = std::thread([this]() {
std::vector<uint8_t> buffer(4096);
while (running_.load()) {
try {
auto size = receive(buffer.data(), buffer.size());
if (size > 0) {
std::lock_guard<std::mutex> lock(queue_mutex_);
recv_queue_.emplace(buffer.begin(), buffer.begin() + static_cast<long long>(size));
}
}
catch (...) {
break;
}
}
});
}
bool AsyncTCPClient::try_pop(std::vector<uint8_t> &data) {
std::lock_guard<std::mutex> 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();
}