#ifndef SOCKET_H #define SOCKET_H #include "../Base/expected.h" #include "../Base/export.h" #include "../Base/codec.h" #include "../JSON.h" #include "Core/spdlog/export.h" #include "NetError.h" #include #include /* 套接字连接过程 客户端(发数据端口)/服务端(收数据端口) 1. 创建套接字 2. 绑定地址和端口 (bind) 3. 监听连接 (listen) / 接受连接 (accept) 4. send() recv() 5. 关闭连接 (close) */ namespace Psc::socket { Ret create_socket_fd(Socket_Type type); Ret set_reuse(Socket_FD that, bool enable); // 开启了一个调试模式,允许内核在网络操作中记录详细的信息。可以通过查看内核日志或tcpdump、Wireshark、strace来实际观察这些调试信息。 Ret set_debug(Socket_FD that, bool enable); Ret set_block(Socket_FD that, bool blocking); Ret set_reuse_addr(Socket_FD that, bool enable); Ret set_buffer_size(Socket_FD that, size_t buffer_size); Ret> select_write(std::vector fds, int timeout_ms); Ret> select_read(const std::vector &recv_fd_vector, int timeout_ms); Ret select_write(Socket_FD that, int timeout_ms); Ret select_read(Socket_FD that, int timeout_ms); Ret get_addr(Socket_FD that); Ret get_dest_addr(Socket_FD that); std::string socket_base_info(Socket_FD that); // 对于 TCP 套接字,fd 是一个已经连接的套接字(通过 connect() 或 accept() // 获得的)。 对于 UDP 套接字,你可以使用 connect() // 指定一个默认的目标地址(然后使用 send()),或者直接使用 sendto() // 来指定目标地址。 // NetError::in_progress // NetError::invalid_argument Ret connect(Socket_FD that, const Sockaddr_In &addr); Ret close(Socket_FD that); Ret send(Socket_FD connected_fd, const std::string &data); Ret send(Socket_FD connected_fd, void* data, std::size_t size); Ret recv_all(Socket_FD connected_fd); Ret recv_once(Socket_FD fd, int chunk_size); Ret bind(Socket_FD that, const Sockaddr_In &addr); Ret recv_all_until_idle(Socket_FD that, int chunk_size, size_t max_bytes, int idle_timeout_ms, bool eof_is_ok ); namespace TCP { Ret set_no_delay(Socket_FD that, bool no_delay); Ret set_keep_alive(Socket_FD that, bool enable); Ret> accept(Socket_FD that); Ret listen(Socket_FD that, int backlog); } // namespace TCP namespace UDP { Ret sendto(Socket_FD that, const std::string &client_ip, uint16_t client_port, const std::string &data); Ret recvfrom(Socket_FD receive_fd, Sockaddr_In *ret, int chunk_size = 1024 * 1024); } // namespace UDP template std::string Ret_To_String(const Ret &r) { auto ec = r.error(); std::ostringstream oss; oss << "【" << to_string(ec.nerr) << "】[" << "]"; if (ec.native) { auto& nec = ec.native; oss << " native【" << nec.category().name() << ":" << nec.value() << "】[" << Psc::platform_2_utf8(nec.message()) << "]"; } return oss.str(); } class Socket_Base { public: virtual ~Socket_Base() = default; std::optional address; Socket_FD socket_fd = -1; virtual std::string to_string() { return address->to_string(); } [[nodiscard]] JSON to_Json() const; virtual void close() { auto r = socket::close(socket_fd); if (!r) { socket_logger->c_debug({}, {}, to_string() + "关闭失败!"); } socket_fd = -1; } }; bool is_needed_reconnect_ec(ERROR_CODE_TYPE r); bool is_needed_reconnect(Socket_FD that); bool is_client_need_close_ec(ERROR_CODE_TYPE r); bool is_client_need_close(Socket_FD that); } // namespace Psc::socket #endif // SOCKET_H