acl/lib_acl_cpp/include/acl_cpp/stream/server_socket.hpp
2023-06-20 09:56:37 +08:00

164 lines
3.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "../acl_cpp_define.hpp"
#include "../stdlib/string.hpp"
#include "../stdlib/noncopyable.hpp"
#if defined(_WIN32) || defined(_WIN64)
#include <WinSock2.h>
#endif
#if __cplusplus >= 201103L
#include <memory>
#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*} 返回空表示接收失败或超时, 返回的流对象在用
* 完用户需要自行 delete 流对象.
*/
socket_stream* accept(int timeout = -1, bool* etimed = NULL);
#if __cplusplus >= 201103L
// 使用 c++11 shared_ptr 方式获得客户端流对象, 更安全地使用流对象
using shared_stream = std::shared_ptr<socket_stream>;
shared_stream shared_accept(int timeout = -1, bool* etimed = NULL) {
shared_stream ss(accept(timeout, etimed));
return ss;
}
#endif
/**
* 获得监听的地址
* @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