Initial commit

This commit is contained in:
2026-06-16 10:56:40 +08:00
commit d2f95e0e27
2047 changed files with 619063 additions and 0 deletions
+421
View File
@@ -0,0 +1,421 @@
#include "Core/Bit.h"
#include "Core/RET.hpp"
#include "Core/Statistics/Frequency_Limit.h"
#include "Socket_p.h"
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#ifdef __linux__
#include <netinet/tcp.h>
#endif
#undef max
#undef min
namespace Psc::socket {
BaseLogger *socket_logger = nullptr;
std::string Sockaddr_In::to_string() const {
return ip + ":" + std::to_string(port);
}
JSON Socket_Base::to_Json() const {
JSON ret = JSON::object();
ret.append({"fd", socket_fd});
ret.append({"address",
address.has_value() ? address.value().to_string() : "nullopt"});
return ret;
}
void log_error(BaseLogger *logger, const std::string &POS,
Psc::socket::Socket_FD fd, const std::string &MSG) {
static Frequency_Limit_Multi lm;
bool ok = lm.test(std::to_string(fd) + "_" + Psc::to_string(last_socket_ec()) + POS);
if (!ok)
return;
std::string msg =
MSG + std::string(" ") + Psc::get_error_message() + " " + POS + "\n";
if (!logger) {
std::ostringstream oss;
oss << "fd:" << fd << " " << msg << std::flush;
std::cout << oss.str();
} else {
static Log_Type log_type({VAR_STR_1(fd)});
logger->error("", log_type, msg);
}
}
Ret<Socket_FD> create_socket_fd(Socket_Type type) {
if (type == Socket_Type::Null) {
socket_logger->c_debug({}, {}, "严重错误 Socket type is Null: " + to_string(type));
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
int t = (type == Socket_Type::TCP) ? SOCK_STREAM : SOCK_DGRAM;
#if defined(__linux__) && defined(SOCK_CLOEXEC)
// 尽量在 socket() 阶段原子设置(避免 fork/exec 竞争窗口)
t |= SOCK_CLOEXEC;
#endif
Socket_FD fd = ::socket(AF_INET, t, 0);
if (fd == INVALID_SOCKET) {
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::unknown_error));
}
return fd;
}
Ret<void> set_buffer_size(Socket_FD that, size_t buffer_size) {
// setsockopt(SO_RCVBUF) 在各平台基本都要求 int
if (buffer_size > static_cast<size_t>(std::numeric_limits<int>::max())) {
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
int sz = static_cast<int>(buffer_size);
// Windows 的 optval 类型是 const char*POSIX 是 const void*
#ifdef _WIN32
const char* optval = reinterpret_cast<const char*>(&sz);
#else
const void* optval = reinterpret_cast<const void*>(&sz);
#endif
if (::setsockopt(that, SOL_SOCKET, SO_RCVBUF, optval,
static_cast<socklen_t>(sizeof(sz))) == SOCKET_ERROR) {
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::unknown_error));
}
return {};
}
Ret<void> close(Socket_FD that) {
if (that != -1) {
#ifdef _WIN32
int r = ::closesocket(that);
#else
int r = ::close(that); // 使用 POSIX 的 close 函数
#endif
if (r == SOCKET_ERROR) {
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::unknown_error));
}
}
return Ret<void>();
}
Ret<void> bind(Socket_FD that, const Sockaddr_In& addr_in) {
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(addr_in.port);
if (inet_pton(AF_INET, addr_in.ip.c_str(), &addr.sin_addr) <= 0) {
static Frequency_Limit fl;
if (fl.test()) {
//LOG_FD_Debug(that, VAR_STR_2(addr_in.ip, addr_in.port) + "不合法的地址!");
}
// 标准错误码:参数非法
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
if (::bind(that, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == SOCKET_ERROR) {
static Frequency_Limit fl;
if (fl.test()) {
//LOG_FD_Debug(that, VAR_STR_2(addr_in.ip, addr_in.port) + "绑定ip端口错误!");
}
// 标准错误码:直接上报系统错误(Windows=WSAGetLastError, Linux=errno
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::unknown_error));
}
return {};
}
Ret<int> send(Socket_FD connected_fd, void *data, std::size_t size) {
#ifdef _WIN32
int flags = 0;
#else
int flags = MSG_NOSIGNAL;
#endif
const int bytes_sent =
::send(connected_fd, (const char *)data, static_cast<int>(size), flags);
if (bytes_sent >= 0) {
return bytes_sent; // 可能是部分发送,交给上层处理
}
#ifdef _WIN32
const int e = ::WSAGetLastError();
// 暂态:直接忽略(不报错),让上层保留缓冲下次继续发
if (e == WSAEWOULDBLOCK || e == WSAEINTR || e == WSAEINPROGRESS || e == WSAEALREADY) {
return 0;
}
#else
const int e = errno;
// 暂态:直接忽略(不报错)
if (e == EAGAIN
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
|| e == EWOULDBLOCK
#endif
|| e == EINTR || e == EINPROGRESS || e == EALREADY) {
return 0;
}
#endif
// 其它错误:返回错误(带 native 错误码,供上层决定是否 close)
const auto ne = NetErrorCategory::map_system_error(e);
return unexpected<Enum_Err<NetError>>(Enum_Err(ne, e));
}
Ret<int> send(Socket_FD connected_fd, const std::string &data) {
if (data.empty()) {
return 0;
}
return send(connected_fd, (uint8_t*)data.data(), data.size());
}
namespace TCP {
Ret<void> set_no_delay(Socket_FD that, bool no_delay) {
int flag = no_delay ? 1 : 0;
auto ret = setsockopt(that, IPPROTO_TCP, TCP_NODELAY,
reinterpret_cast<char *>(&flag), sizeof(flag));
if (ret < 0) {
LOG_FD_Debug(that, "设置socket阻塞属性错误!")
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
return Ret<void>();
}
Ret<void> set_keep_alive(Socket_FD that, bool enable) {
int flag = enable ? 1 : 0;
auto ret = setsockopt(that, SOL_SOCKET, SO_KEEPALIVE,
reinterpret_cast<char *>(&flag), sizeof(flag));
if (ret < 0) {
LOG_FD_Debug(that, VAR_STR_2(that, enable) + "无法设置 SO_KEEPALIVE!")
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
return Ret<void>();
}
Ret<void> listen(Socket_FD that, int backlog) {
if (::listen(that, backlog) == SOCKET_ERROR) {
auto ec = last_socket_ec();
LOG_FD_Debug(that,
VAR_STR_2(that, backlog) +
"listen 错误");
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
return Ret<void>();
}
} // namespace TCP
namespace UDP {
Ret<int> sendto(Socket_FD that, const std::string &client_ip,
uint16_t client_port, const std::string &data) {
#ifdef _WIN32
int flags = 0;
#else
int flags = MSG_NOSIGNAL; // UDP 一般不需要,但保留也无妨
#endif
if (data.empty()) {
return 0; // 发送 0 字节:正常
}
sockaddr_in client_addr{};
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(client_port);
if (inet_pton(AF_INET, client_ip.c_str(), &client_addr.sin_addr) <= 0) {
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
int bytes_sent = ::sendto(
that, data.data(), static_cast<int>(data.size()), flags,
reinterpret_cast<const sockaddr *>(&client_addr), sizeof(client_addr));
if (bytes_sent == SOCKET_ERROR) {
auto ec = last_socket_ec();
LOG_FD_Debug(that, std::string("sendto error: ") + get_error_message());
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::unknown_error));
}
// UDP sendto 成功时通常 >0;若出现 0,多半是 data 为空(已提前返回)
return bytes_sent;
}
} // namespace UDP
void get_fd_set(const std::vector<Socket_FD> &fds, fd_set &ret_fd_set,
int &max_fd) {
FD_ZERO(&ret_fd_set); // 清空读集合
// 初始化最大文件描述符为 -1
max_fd = -1;
// 将所有套接字添加到fd_set中,并找到最大套接字描述符
for (Socket_FD fd : fds) {
FD_SET(fd, &ret_fd_set);
if (fd > max_fd) {
max_fd = fd; // 更新最大文件描述符
}
}
}
timeval get_timeout(int timeout_ms) {
timeval timeout{};
timeout.tv_sec = timeout_ms / 1000; // 秒
timeout.tv_usec = (timeout_ms % 1000) * 1000; // 微秒
return timeout;
}
Ret<std::vector<Socket_FD>>
select_read(const std::vector<Socket_FD> &recv_fd_vector, int timeout_ms) {
std::vector<Socket_FD> ret;
fd_set fds;
int max_fd = -1;
get_fd_set(recv_fd_vector, fds, max_fd);
timeval timeout = get_timeout(timeout_ms);
int result = select(max_fd + 1, &fds, nullptr, nullptr, &timeout);
if (result <= 0) {
return ret;
}
for (Socket_FD fd : recv_fd_vector) {
if (FD_ISSET(fd, &fds)) {
ret.push_back(fd);
}
}
return ret;
}
Ret<std::vector<Socket_FD>> select_write(std::vector<Socket_FD> fd_vector,
int timeout_ms) {
std::vector<Socket_FD> ret;
fd_set fds;
int max_fd = -1;
get_fd_set(fd_vector, fds, max_fd);
timeval timeout = get_timeout(timeout_ms);
int result = select(max_fd + 1, nullptr, &fds, nullptr, &timeout);
if (result <= 0) {
return ret;
}
for (Socket_FD fd : fd_vector) {
if (FD_ISSET(fd, &fds)) {
ret.push_back(fd);
}
}
return ret;
}
Ret<bool> select_write(Socket_FD that, int timeout_ms) {
auto r = select_write(std::vector<Socket_FD>{that}, timeout_ms);
if (!r) {
return false;
}
return !r.value().empty();
}
Ret<bool> select_read(Socket_FD that, int timeout_ms) {
auto r = select_read(std::vector<Socket_FD>{that}, timeout_ms);
if (!r) {
return false;
}
return !r.value().empty();
}
Ret<Sockaddr_In> get_dest_addr(Socket_FD that) {
Sockaddr_In ret;
sockaddr_in addr{};
socklen_t addrLen = sizeof(addr);
if (::getpeername(that, reinterpret_cast<sockaddr*>(&addr), &addrLen) == SOCKET_ERROR) {
LOG_FD_Debug(that, "获取目标地址错误!");
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
char ipbuf[INET_ADDRSTRLEN]{};
if (!::inet_ntop(AF_INET, &addr.sin_addr, ipbuf, sizeof(ipbuf))) {
// inet_ntop 失败:返回标准错误
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
ret.ip = ipbuf;
ret.port = ntohs(addr.sin_port);
return ret;
}
Ret<Sockaddr_In> get_addr(Socket_FD that) {
Sockaddr_In ret;
sockaddr_in localAddr{};
socklen_t addrLen = sizeof(localAddr);
if (::getsockname(that, reinterpret_cast<sockaddr*>(&localAddr), &addrLen) == SOCKET_ERROR) {
LOG_FD_Debug(that, "获取socket地址错误!");
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::unknown_error)); // 或 get_sys_ex()
}
char ipbuf[INET_ADDRSTRLEN]{};
if (!::inet_ntop(AF_INET, &localAddr.sin_addr, ipbuf, sizeof(ipbuf))) {
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument));
}
ret.ip = ipbuf;
ret.port = ntohs(localAddr.sin_port);
return ret;
}
std::string socket_base_info(Socket_FD that) {
auto addr = get_addr(that);
auto dest_addr = get_dest_addr(that);
auto s1 = addr ? addr->to_string() : Psc::to_string(addr.error());
auto s2 = dest_addr ? dest_addr->to_string() : to_string(dest_addr.error());
return "[" + s1 + "]=>[" + s2 + "]";
}
Ret<void> set_reuse(Socket_FD that, bool enable) {
int flag = enable ? 1 : 0;
auto ret = setsockopt(that, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char *>(&flag), sizeof(flag));
if (ret < 0) {
LOG_FD_Debug(that, VAR_STR_2(that, enable) +
"无法设置 SO_REUSEADDR!")
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument, ret));
}
return Ret<void>();
}
Ret<void> set_debug(Socket_FD that, bool enable) {
int flag = enable ? 1 : 0;
auto ret = setsockopt(that, SOL_SOCKET, SO_DEBUG,
reinterpret_cast<char *>(&flag), sizeof(flag));
if (ret < 0) {
LOG_FD_Debug(that, VAR_STR_2(that, enable) + "无法设置 SO_DEBUG!")
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument, ret));
}
return Ret<void>();
}
Ret<int> get_socket_opt(Socket_FD fd, int optname) {
int optionValue;
socklen_t optionLen = sizeof(optionValue);
auto r = getsockopt(fd, SOL_SOCKET, optname,
reinterpret_cast<char *>(&optionValue), &optionLen);
if (r == SOCKET_ERROR) {
LOG_FD_Debug(fd, std::to_string(optname) + "获取套接字错误!")
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument, r));
}
return optionValue;
}
Ret<void> set_reuse_addr(Socket_FD that, bool enable) {
int opt = enable ? 1 : 0;
auto r = setsockopt(that, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt,
sizeof(opt));
if (r == SOCKET_ERROR) {
return unexpected<Enum_Err<NetError>>(Enum_Err(NetError::invalid_argument, r));
}
return Ret<void>();
}
} // namespace Psc::socket
#undef SOCKET_END