116 lines
3.8 KiB
C++
116 lines
3.8 KiB
C++
#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 <cstdint>
|
|
#include <set>
|
|
|
|
/*
|
|
套接字连接过程 客户端(发数据端口)/服务端(收数据端口)
|
|
1. 创建套接字
|
|
2. 绑定地址和端口 (bind)
|
|
3. 监听连接 (listen) / 接受连接 (accept)
|
|
4. send() recv()
|
|
5. 关闭连接 (close)
|
|
*/
|
|
namespace Psc::socket {
|
|
Ret<Socket_FD> create_socket_fd(Socket_Type type);
|
|
Ret<void> set_reuse(Socket_FD that, bool enable);
|
|
// 开启了一个调试模式,允许内核在网络操作中记录详细的信息。可以通过查看内核日志或tcpdump、Wireshark、strace来实际观察这些调试信息。
|
|
Ret<void> set_debug(Socket_FD that, bool enable);
|
|
Ret<void> set_block(Socket_FD that, bool blocking);
|
|
Ret<void> set_reuse_addr(Socket_FD that, bool enable);
|
|
Ret<void> set_buffer_size(Socket_FD that, size_t buffer_size);
|
|
Ret<std::vector<Socket_FD>> select_write(std::vector<Socket_FD> fds,
|
|
int timeout_ms);
|
|
Ret<std::vector<Socket_FD>> select_read(const std::vector<Socket_FD> &recv_fd_vector, int timeout_ms);
|
|
Ret<bool> select_write(Socket_FD that, int timeout_ms);
|
|
Ret<bool> select_read(Socket_FD that, int timeout_ms);
|
|
Ret<Sockaddr_In> get_addr(Socket_FD that);
|
|
Ret<Sockaddr_In> 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<bool> connect(Socket_FD that, const Sockaddr_In &addr);
|
|
|
|
|
|
Ret<void> close(Socket_FD that);
|
|
|
|
Ret<int> send(Socket_FD connected_fd, const std::string &data);
|
|
Ret<int> send(Socket_FD connected_fd, void* data, std::size_t size);
|
|
Ret<std::string> recv_all(Socket_FD connected_fd);
|
|
Ret<std::string> recv_once(Socket_FD fd, int chunk_size);
|
|
Ret<void> bind(Socket_FD that, const Sockaddr_In &addr);
|
|
Ret<std::string> 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<void> set_no_delay(Socket_FD that, bool no_delay);
|
|
Ret<void> set_keep_alive(Socket_FD that, bool enable);
|
|
|
|
Ret<std::optional<Accept_Info>> accept(Socket_FD that);
|
|
|
|
Ret<void> listen(Socket_FD that, int backlog);
|
|
|
|
} // namespace TCP
|
|
namespace UDP {
|
|
Ret<int> sendto(Socket_FD that, const std::string &client_ip,
|
|
uint16_t client_port, const std::string &data);
|
|
Ret<std::string> recvfrom(Socket_FD receive_fd, Sockaddr_In *ret,
|
|
int chunk_size = 1024 * 1024);
|
|
} // namespace UDP
|
|
|
|
|
|
|
|
template <typename T> std::string Ret_To_String(const Ret<T> &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<Sockaddr_In> 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
|