#pragma once #include "../acl_cpp_define.hpp" #include "../stdlib/string.hpp" #include "../stdlib/noncopyable.hpp" #if defined(_WIN32) || defined(_WIN64) #include #endif namespace acl { class socket_stream; enum { OPEN_FLAG_NONE = 0, OPEN_FLAG_NONBLOCK = 1, // 非阻塞模式 OPEN_FLAG_REUSEPORT = 1 << 1, // 端口复用,要求 Linux3.0 以上 OPEN_FLAG_FASTOPEN = 1 << 2, // 是否启用 Fast open(实验阶段) OPEN_FLAG_EXCLUSIVE = 1 << 3, // 是否禁止复用地址 }; /** * 服务端监听套接口类,接收客户端连接,并创建客户端流连接对象 */ class ACL_CPP_API server_socket : public noncopyable { public: #if 0 /** * 构造函数,调用本构造函数后需调用类方法 open 来监听指定服务地址 * @param backlog {int} 监听套接口队列长度 * @param block {bool} 是阻塞模式还是非阻塞模式 */ server_socket(int backlog, bool block); #endif /** * 构造函数 * @param flag {unsigned} 定义参见 OPEN_FLAG_XXX * @param backlog {int} 监听套接口队列长度 */ server_socket(unsigned flag, int backlog); /** * 构造函数,调用本构造函数后禁止再调用 open 方法 * @param sstream {ACL_VSTREAM*} 外部创建的监听流对象,本类仅使用 * 但并不释放,由应用自行关闭该监听对象 */ server_socket(ACL_VSTREAM* sstream); /** * 构造函数,调用本构造函数后禁止再调用 open 方法 * @param fd {ACL_SOCKET} 外部创建的监听句柄,本类仅使用但并不释放, * 由应用自行关闭该监听句柄 */ #if defined(_WIN32) || defined(_WIN64) server_socket(SOCKET fd); #else server_socket(int fd); #endif server_socket(void); ~server_socket(void); /** * 开始监听给定服务端地址 * @param addr {const char*} 服务器监听地址,格式为: * ip:port;在 unix 环境下,还可以是域套接口,格式为:/path/xxx,在 * Linux 平台下,如果域套接口地址为:@xxx 格式,即第一个字母为 @ 则 * 内部自动启用 Linux 下的抽象域套接字方式(abstract unix socket) * @return {bool} 监听是否成功 */ bool open(const char* addr); /** * 判断当前监听套接口是否打开着 * @return {bool} */ bool opened(void) const; /** * 关闭已经打开的监听套接口 * @return {bool} 是否正常关闭 */ bool close(void); /** * 将监听套接口从服务监听对象中解绑 * @return {SOCKET} 返回被解绑的句柄 */ #if defined(_WIN32) || defined(_WIN64) SOCKET unbind(void); #else int unbind(void); #endif /** * 接收客户端连接并创建客户端连接流 * @param timeout {int} 当该值 >= 0 时,采用超时方式接收客户端连接, * 若在指定时间内未获得客户端连接,则返回 NULL * @param etimed {bool*} 当此指针非 NULL 时,如果因超时导致该函数返回 * NULL,则此值被置为 true * @return {socket_stream*} 返回空表示接收失败或超时 */ socket_stream* accept(int timeout = -1, bool* etimed = NULL); /** * 获得监听的地址 * @return {const char*} 返回值非空指针 */ const char* get_addr(void) const { return addr_.c_str(); } /** * 当正常监听服务器地址后调用本函数可以获得监听套接口 * @return {int} */ #if defined(_WIN32) || defined(_WIN64) SOCKET sock_handle(void) const #else int sock_handle(void) const #endif { return fd_; } /** * 设置监听套接字的延迟接收功能,即当客户端连接上有数据时才将该连接返回 * 给应用,目前该功能仅支持 Linux * @param timeout {int} 如果客户端连接在规定的时间内未发来数据, * 也将该连接返回给应用 */ void set_tcp_defer_accept(int timeout); private: int backlog_; unsigned open_flag_; bool unix_sock_; string addr_; #if defined(_WIN32) || defined(_WIN64) SOCKET fd_; SOCKET fd_local_; #else int fd_; int fd_local_; #endif }; } // namespace acl