#pragma once #ifndef PLANTSUNCAT_ERRC_H #define PLANTSUNCAT_ERRC_H #include "Core/Base/export.h" namespace Psc::socket { enum class NetError : unsigned char { // ===== 通用 / 取消 / 参数 ===== unknown_error, // 被信号/中断打断(EINTR / WSAEINTR) interrupted, // 被信号/中断打断(EINTR / WSAEINTR) operation_canceled, // 取消(ECANCELED / WSAECANCELLED) invalid_argument, // 参数非法(EINVAL / WSAEINVAL) not_supported, // 不支持(EOPNOTSUPP/ENOTSUP 等) permission_denied, // 权限不足(EACCES) out_of_memory, // 内存不足(ENOMEM) resource_exhausted, // 资源耗尽(EMFILE/ENFILE/ENOBUFS 等) // ===== I/O / 系统 ===== io_error, // 其他 I/O 错误(EIO 等) bad_file_descriptor, // fd 无效(EBADF) not_a_socket, // 不是 socket(ENOTSOCK / WSAENOTSOCK) // ===== 非阻塞 / 状态 ===== would_block, // 非阻塞下暂时无数据/不可写(EAGAIN/EWOULDBLOCK / WSAEWOULDBLOCK) in_progress, // 操作进行中(EINPROGRESS / WSAEINPROGRESS) already_in_progress, // 已经在进行(EALREADY / WSAEALREADY) // ===== 地址 / 协议 ===== address_in_use, // 地址端口被占用(EADDRINUSE / WSAEADDRINUSE) address_not_available, // 地址不可用(EADDRNOTAVAIL / WSAEADDRNOTAVAIL) network_down, // 网络子系统 down(ENETDOWN / WSAENETDOWN) network_unreachable, // 网络不可达(ENETUNREACH / WSAENETUNREACH) host_unreachable, // 主机不可达(EHOSTUNREACH / WSAEHOSTUNREACH) protocol_error, // 协议/选项错误(EPROTO/EPROTOTYPE/ENOPROTOOPT...) // ===== 连接语义(TCP 核心)===== not_connected, // 未连接(ENOTCONN / WSAENOTCONN) already_connected, // 已连接(EISCONN / WSAEISCONN) connection_refused, // 连接被拒绝(ECONNREFUSED / WSAECONNREFUSED) connection_reset, // 连接被重置(ECONNRESET / WSAECONNRESET) connection_aborted, // 连接被中止(ECONNABORTED / WSAECONNABORTED) connection_closed, // 对端正常关闭/EOF(recv 返回 0 的语义) timed_out, // 超时(ETIMEDOUT / WSAETIMEDOUT) broken_pipe, // 写入已关闭连接(EPIPE;Windows 近似用 shutdown/notconn/reset) // ===== DNS / 名称解析(可选但建议)===== dns_not_found, // host 不存在/找不到(HOST_NOT_FOUND) dns_temporary_failure, // 临时失败(TRY_AGAIN) dns_failure, // 其他解析失败(NO_RECOVERY / 语义较泛) }; class NetErrorCategory final : public std::error_category { public: [[nodiscard]] const char* name() const noexcept override { // enum_type_name 返回 string_view,静态存储即可 static constexpr auto name_sv = magic_enum::enum_type_name(); return name_sv.data(); } [[nodiscard]] std::string message(int ev) const override { auto opt = magic_enum::enum_name(static_cast(ev)); if (!opt.empty()) return std::string(opt); return "unknown enum error"; } [[nodiscard]] bool equivalent(const std::error_code& ec, int cond) const noexcept override { if (ec.category() != std::system_category()) return false; return map_system_error(ec.value()) == static_cast(cond); } static NetError map_system_error(int e) noexcept; }; inline const std::error_category& net_category() { static NetErrorCategory cat; return cat; } ERROR_CODE_TYPE last_socket_ec(); template using Ret = expected>; extern BaseLogger *socket_logger; #if WIN32 using Socket_FD = unsigned long long; #else using Socket_FD = int; #endif // 默认IPV4 TCP enum class Socket_Type { TCP, UDP, Null }; struct Sockaddr_In { std::string ip; std::uint32_t port{}; [[nodiscard]] std::string to_string() const; Sockaddr_In() = default; Sockaddr_In(const std::string &ip, std::uint32_t port) { this->ip = ip; this->port = port; } // 定义小于运算符,便于存入 std::set bool operator<(const Sockaddr_In &other) const { // 先比较 IP 地址 if (ip != other.ip) { return ip < other.ip; } // 如果 IP 地址相同,再比较端口号 return port < other.port; } bool operator==(const Sockaddr_In &other) const noexcept { return ip == other.ip && port == other.port; } bool operator!=(const Sockaddr_In &other) const noexcept { return !(*this == other); } }; struct Accept_Info { Sockaddr_In sockaddr; Socket_FD fd{}; [[nodiscard]] std::string to_string() const { return "fd:" + std::to_string(fd) + ":[" + sockaddr.to_string() + "]"; } }; } #endif