initial commit

This commit is contained in:
2025-08-05 15:53:44 +08:00
commit 09dc02ae52
553 changed files with 137665 additions and 0 deletions

656
third_party/libhv/docs/API.md vendored Executable file
View File

@@ -0,0 +1,656 @@
# libhv API Manual
## base
### hplatform.h
- OS: OS_WIN, OS_UNIX (OS_LINUX, OS_ANDROID, OS_DARWIN ...)
- ARCH: ARCH_X86, ARCH_X64, ARCH_ARM, ARCH_ARM64
- COMPILER: COMPILER_MSVC, COMPILER_MINGW, COMPILER_GCC, COMPILER_CLANG
- BYTE_ORDER: BIG_ENDIAN, LITTLE_ENDIAN
- stdbool.h: bool, true, false
- stdint.h: int8_t, int16_t, int32_t, int64_t
- hv_sleep, hv_msleep, hv_usleep, hv_delay
- hv_mkdir
- stricmp, strcasecmp
### hexport.h
- HV_EXPORT, HV_INLINE
- HV_SOURCE, HV_STATICLIB, HV_DYNAMICLIB
- HV_DEPRECATED
- HV_UNUSED
- EXTERN_C, BEGIN_EXTERN_C, END_EXTERN_C
- BEGIN_NAMESPACE, END_NAMESPACE, USING_NAMESPACE
- DEFAULT
- ENUM, STRUCT
- IN, OUT, INOUT
- OPTIONAL, REQUIRED, REPEATED
### hdef.h
- ABS, NABS
- ARRAY_SIZE
- BITSET, BITCLR, BITGET
- CR, LF, CRLF
- FLOAT_EQUAL_ZERO
- INFINITE
- IS_ALPHA, IS_DIGIT, IS_ALPHANUM
- IS_CNTRL, IS_GRAPH
- IS_HEX
- IS_LOWER, IS_UPPER
- LOWER, UPPER
- MAKEWORD, LOBYTE, HIBYTE
- MAKELONG, LOWORD, HIWORD
- MAKEINT64, LOINT, HIINT
- MAKE_FOURCC
- MAX, MIN, LIMIT
- MAX_PATH
- NULL, TRUE, FALSE
- SAFE_FREE, SAFE_DELETE, SAFE_DELETE_ARRAY, SAFE_RELEASE
- STRINGCAT
- STRINGIFY
- offsetof, offsetofend
- container_of
- prefetch
- printd, printe
### hatomic.h
- hatomic_flag_t, hatomic_t
- hatomic_flag_test_and_set
- hatomic_flag_clear
- hatomic_add
- hatomic_sub
- hatomic_inc
- hatomic_dec
### herr.h
- hv_strerror
### htime.h
- IS_LEAP_YEAR
- datetime_t
- gettick_ms
- gettimeofday
- gettimeofday_ms
- gettimeofday_us
- gethrtime_us
- datetime_now
- datetime_localtime
- datetime_mktime
- datetime_past
- datetime_future
- duration_fmt
- datetime_fmt
- gmtime_fmt
- days_of_month
- month_atoi
- month_itoa
- weekday_atoi
- weekday_itoa
- hv_compile_datetime
- cron_next_timeout
### hmath.h
- floor2e
- ceil2e
- varint_encode
- varint_decode
### hbase.h
- hv_malloc
- hv_calloc
- hv_realloc
- hv_zalloc
- hv_strncpy
- hv_strncat
- hv_strlower
- hv_strupper
- hv_strreverse
- hv_strstartswith
- hv_strendswith
- hv_strcontains
- hv_wildcard_match
- hv_strnchr
- hv_strrchr_dot
- hv_strrchr_dir
- hv_basename
- hv_suffixname
- hv_mkdir_p
- hv_rmdir_p
- hv_exists
- hv_isdir
- hv_isfile
- hv_islink
- hv_filesize
- get_executable_path
- get_executable_dir
- get_executable_file
- get_run_dir
- hv_rand
- hv_random_string
- hv_getboolean
- hv_parse_size
- hv_parse_time
- hv_parse_url
### hversion.h
- hv_version
- hv_compile_version
- version_atoi
- version_itoa
### hsysinfo.h
- get_ncpu
- get_meminfo
### hproc.h
- hproc_spawn
### hthread.h
- hv_getpid
- hv_gettid
- HTHREAD_RETTYPE
- HTHREAD_ROUTINE
- hthread_create
- hthread_join
- class HThread
### hmutex.h
- hmutex_t
- hmutex_init
- hmutex_destroy
- hmutex_lock
- hmutex_unlock
- hspinlock_t
- hspinlock_init
- hspinlock_destroy
- hspinlock_lock
- hspinlock_unlock
- hrwlock_t
- hrwlock_init
- hrwlock_destroy
- hrwlock_rdlock
- hrwlock_rdunlock
- hrwlock_wrlock
- hrwlock_wrunlock
- htimed_mutex_t
- htimed_mutex_init
- htimed_mutex_destroy
- htimed_mutex_lock
- htimed_mutex_lock_for
- htimed_mutex_unlock
- hcondvar_t
- hcondvar_init
- hcondvar_destroy
- hcondvar_wait
- hcondvar_wait_for
- hcondvar_signal
- hcondvar_broadcast
- hsem_init
- hsem_destroy
- hsem_wait
- hsem_post
- hsem_timedwait
- honce_t
- HONCE_INIT
- honce
- class `hv::MutexLock`
- class `hv::SpinLock`
- class `hv::RWLock`
- class `hv::LockGuard`
- synchronized
### hsocket.h
- INVALID_SOCKET
- closesocket
- blocking
- nonblocking
- Bind
- Listen
- Connect
- ConnectNonblock
- ConnectTimeout
- ResolveAddr
- Socketpair
- socket_errno
- socket_strerror
- sockaddr_u
- sockaddr_ip
- sockaddr_port
- sockaddr_set_ip
- sockaddr_set_port
- sockaddr_set_ipport
- sockaddr_len
- sockaddr_str
- sockaddr_print
- SOCKADDR_LEN
- SOCKADDR_STR
- SOCKADDR_PRINT
- tcp_nodelay
- tcp_nopush
- tcp_keepalive
- udp_broadcast
- ip_v6only
- so_sndtimeo
- so_rcvtimeo
- so_sndbuf
- so_rcvbuf
- so_reuseaddr
- so_reuseport
- so_linger
### hlog.h
- default_logger
- file_logger
- stderr_logger
- stdout_logger
- logger_create
- logger_destroy
- logger_enable_color
- logger_enable_fsync
- logger_fsync
- logger_print
- logger_set_file
- logger_set_handler
- logger_set_level
- logger_set_max_bufsize
- logger_set_max_filesize
- logger_set_remain_days
- logger_get_cur_file
- hlogd, hlogi, hlogw, hloge, hlogf
- LOGD, LOGI, LOGW, LOGE, LOGF
### hbuf.h
- hbuf_t
- offset_buf_t
- class HBuf
- class HVLBuf
- class HRingBuf
### hmain.h
- main_ctx_init
- parse_opt
- parse_opt_long
- dump_opt_long
- get_arg
- get_env
- setproctitle
- signal_init
- signal_handle
- create_pidfile
- delete_pidfile
- getpid_form_pidfile
- master_workers_run
### hstring.h
- to_string
- from_string
- toupper
- tolower
- reverse
- startswith
- endswith
- contains
- asprintf
- trim
- ltrim
- rtrim
- trim_pairs
- split
- splitKV
- replace
- replaceAll
### hfile.h
- class HFile
### hpath.h
- exists
- isdir
- isfile
- islink
- basename
- dirname
- filename
- suffixname
- join
### hdir.h
- listdir
### hurl.h
- HUrl::escape
- HUrl::unescape
- HUrl::parse
- HUrl::dump
### hscope.h
- defer
- template ScopeCleanup
- template ScopeFree
- template ScopeDelete
- template ScopeDeleteArray
- template ScopeRelease
- template ScopeLock
### ifconfig.h
- ifconfig
## utils
### md5.h
- HV_MD5Init
- HV_MD5Update
- HV_MD5Final
- hv_md5
- hv_md5_hex
### sha1.h
- HV_SHA1Init
- HV_SHA1Update
- HV_SHA1Final
- HV_SHA1
- hv_sha1
- hv_sha1_hex
### base64.h
- hv_base64_decode
- hv_base64_encode
### json.hpp
- json::parse
- json::dump
### singleton.h
- DISABLE_COPY
- SINGLETON_DECL
- SINGLETON_IMPL
## event
### hloop.h
- hloop_create_tcp_client
- hloop_create_tcp_server
- hloop_create_udp_client
- hloop_create_udp_server
- hloop_create_ssl_client
- hloop_create_ssl_server
- hloop_new
- hloop_free
- hloop_run
- hloop_stop
- hloop_pause
- hloop_resume
- hloop_status
- hloop_pid
- hloop_tid
- hloop_now
- hloop_now_ms
- hloop_now_us
- hloop_update_time
- hloop_set_userdata
- hloop_userdata
- hloop_wakeup
- hloop_post_event
- hevent_loop
- hevent_type
- hevent_id
- hevent_priority
- hevent_userdata
- hevent_set_priority
- hevent_ser_userdata
- haccept
- hconnect
- hread
- hwrite
- hrecv
- hsend
- hrecvfrom
- hsendto
- hio_add
- hio_del
- hio_get
- hio_detach
- hio_attach
- hio_read
- hio_read_start
- hio_read_stop
- hio_read_once
- hio_read_until
- hio_read_until_length
- hio_read_until_delim
- hio_read_readline
- hio_read_readstring
- hio_read_readbytes
- hio_write
- hio_close
- hio_accept
- hio_connect
- hio_fd
- hio_id
- hio_type
- hio_error
- hio_localaddr
- hio_peeraddr
- hio_events
- hio_revents
- hio_is_opened
- hio_is_closed
- hio_enable_ssl
- hio_is_ssl
- hio_get_ssl
- hio_set_ssl
- hio_get_ssl_ctx
- hio_set_ssl_ctx
- hio_new_ssl_ctx
- hio_setcb_accept
- hio_setcb_connect
- hio_setcb_read
- hio_setcb_write
- hio_setcb_close
- hio_getcb_accept
- hio_getcb_connect
- hio_getcb_read
- hio_getcb_write
- hio_getcb_close
- hio_set_type
- hio_set_localaddr
- hio_set_peeraddr
- hio_set_readbuf
- hio_set_connect_timeout
- hio_set_close_timeout
- hio_set_read_timeout
- hio_set_write_timeout
- hio_set_keepalive_timeout
- hio_set_heartbeat
- hio_set_unpack
- hio_unset_unpack
- hio_read_upstream
- hio_write_upstream
- hio_close_upstream
- hio_setup_upstream
- hio_get_upstream
- hio_setup_tcp_upstream
- hio_setup_ssl_upstream
- hio_setup_udp_upstream
- hio_create_socket
- hio_create_pipe
- hio_context
- hio_set_context
- htimer_add
- htimer_add_period
- htimer_del
- htimer_reset
- hidle_add
- hidle_del
- hsignal_add
- hsignal_del
### nlog.h
- network_logger
- nlog_listen
## evpp
- class Buffer
- class Channel
- class Event
- class EventLoop
- class EventLoopThread
- class EventLoopThreadPool
- class TcpClient
- class TcpServer
- class UdpClient
- class UdpServer
## ssl
- hssl_ctx_init
- hssl_ctx_cleanup
- hssl_ctx_instance
- hssl_ctx_new
- hssl_ctx_free
- hssl_new
- hssl_free
- hssl_accept
- hssl_connnect
- hssl_read
- hssl_write
- hssl_close
- hssl_set_sni_hostname
## protocol
### dns.h
- dns_name_decode
- dns_name_encode
- dns_pack
- dns_unpack
- dns_rr_pack
- dns_rr_unpack
- dns_query
- dns_free
- nslookup
### ftp.h
- ftp_command_str
- ftp_connect
- ftp_login
- ftp_exec
- ftp_upload
- ftp_download
- ftp_download_with_cb
- ftp_quit
- ftp_status_str
### smtp.h
- smtp_command_str
- smtp_status_str
- smtp_build_command
- sendmail
### icmp.h
- ping
## http
- class HttpMessage
- class HttpRequest
- class HttpResponse
- class HttpParser
### httpdef.h
- http_content_type_enum
- http_content_type_enum_by_suffix
- http_content_type_str
- http_content_type_str_by_suffix
- http_content_type_suffix
- http_errno_description
- http_errno_name
- http_method_enum
- http_method_str
- http_status_enum
- http_status_str
### http_content.h
- parse_query_params
- parse_json
- parse_multipart
- dump_query_params
- dump_json
- dump_multipart
### HttpClient.h
- http_client_new
- http_client_del
- http_client_send
- http_client_send_async
- http_client_strerror
- http_client_set_timeout
- http_client_set_header
- http_client_del_header
- http_client_get_header
- http_client_clear_headers
- http_client_set_http_proxy
- http_client_set_https_proxy
- http_client_add_no_proxy
- class HttpClient
### requests.h
- requests::request
- requests::get
- requests::post
- requests::put
- requests::patch
- requests::Delete
- requests::head
- requests::async
### axios.h
- axios::axios
- axios::get
- axios::post
- axios::put
- axios::patch
- axios::Delete
- axios::head
- axios::async
### HttpServer.h
- http_server_run
- http_server_stop
- class HttpService
- class HttpServer
### WebSocketClient.h
- class WebSocketClient
### WebSocketServer.h
- websocket_server_run
- websocket_server_stop
- class WebSocketService
- class WebSocketServer
## mqtt
- mqtt_client_new
- mqtt_client_free
- mqtt_client_run
- mqtt_client_stop
- mqtt_client_set_id
- mqtt_client_set_will
- mqtt_client_set_auth
- mqtt_client_set_callback
- mqtt_client_set_userdata
- mqtt_client_get_userdata
- mqtt_client_get_last_error
- mqtt_client_set_ssl_ctx
- mqtt_client_new_ssl_ctx
- mqtt_client_set_reconnect
- mqtt_client_reconnect
- mqtt_client_set_connect_timeout
- mqtt_client_connect
- mqtt_client_is_connected
- mqtt_client_disconnect
- mqtt_client_publish
- mqtt_client_subscribe
- mqtt_client_unsubscribe
- class MqttClient
## other
- class HThreadPool
- class HObjectPool
- class ThreadLocalStorage

31
third_party/libhv/docs/PLAN.md vendored Executable file
View File

@@ -0,0 +1,31 @@
## Done
- base: cross platfrom infrastructure
- event: select/poll/epoll/wepoll/kqueue/port
- ssl: openssl/gnutls/mbedtls/wintls/appletls
- rudp: KCP
- evpp: c++ EventLoop interface similar to muduo and evpp
- http client/server: include https http1/x http2
- websocket client/server
- mqtt client
## Improving
- Path router: optimized matching via trie?
- FileCache use LRUCache
## Plan
- redis client
- async DNS
- lua binding
- js binding
- hrpc = libhv + protobuf
- rudp: FEC, ARQ, UDT, QUIC
- kcptun
- have a taste of io_uring
- coroutine
- cppsocket.io
- IM-libhv
- MediaServer-libhv
- GameServer-libhv

153
third_party/libhv/docs/cn/Channel.md vendored Executable file
View File

@@ -0,0 +1,153 @@
通道类
```c++
class Channel {
// 返回底层的io结构体指针
hio_t* io() { return io_; }
// 返回socket文件描述符
int fd() { return fd_; }
// 返回一个唯一标示id
uint32_t id() { return id_; }
// 返回错误码
int error() { return hio_error(io_); }
// 获取/设置/新建/删除 上下文
void* context();
void setContext(void* ctx);
template<class T> T* newContext();
template<class T> T* getContext();
template<class T> void deleteContext();
// 获取/设置/新建/删除 上下文智能指针
std::shared_ptr<void> contextPtr();
void setContextPtr(const std::shared_ptr<void>& ctx);
void setContextPtr(std::shared_ptr<void>&& ctx);
template<class T> std::shared_ptr<T> newContextPtr();
template<class T> std::shared_ptr<T> getContextPtr();
void deleteContextPtr();
// 是否打开状态
bool isOpened();
// 是否关闭状态
bool isClosed();
// 开始读
int startRead();
// 停止读
int stopRead();
// 读一次
int readOnce();
// 读一个字符串
int readString();
// 读一行
int readLine();
// 读取N个字节
int readBytes(int len);
// 写
int write(const void* data, int size);
int write(Buffer* buf);
int write(const std::string& str);
// 设置最大读缓存
void setMaxReadBufsize(uint32_t size);
// 设置最大写缓存
void setMaxWriteBufsize(uint32_t size);
// 获取当前写缓存大小
size_t writeBufsize();
// 是否写完成
bool isWriteComplete();
// 关闭
int close(bool async = false);
// 读回调
std::function<void(Buffer*)> onread;
// 写回调
std::function<void(Buffer*)> onwrite;
// 关闭回调
std::function<void()> onclose;
};
// SocketChannel 继承自 Channel
class SocketChannel : public Channel {
// 连接状态回调
std::function<void()> onconnect;
// 心跳回调
std::function<void()> heartbeat;
// 启用SSL/TLS加密通信
int enableSSL();
// 是否是SSL/TLS加密通信
bool isSSL();
// 设置SSL
int setSSL(hssl_t ssl);
// 设置SSL_CTX
int setSslCtx(hssl_ctx_t ssl_ctx);
// 新建SSL_CTX
int newSslCtx(hssl_ctx_opt_t* opt);
// 设置主机名
int setHostname(const std::string& hostname);
// 设置连接超时
void setConnectTimeout(int timeout_ms);
// 设置关闭超时 (说明:非阻塞写队列非空时,需要等待写完成再关闭)
void setCloseTimeout(int timeout_ms);
// 设置读超时 (一段时间没有数据到来便自动关闭连接)
void setReadTimeout(int timeout_ms);
// 设置写超时 (一段时间没有数据发送便自动关闭连接)
void setWriteTimeout(int timeout_ms);
// 设置keepalive超时 (一段时间没有数据收发便自动关闭连接)
void setKeepaliveTimeout(int timeout_ms);
// 设置心跳 (定时发送心跳包)
void setHeartbeat(int interval_ms, std::function<void()> fn);
// 设置拆包规则
void setUnpack(unpack_setting_t* setting);
// 开始连接
int startConnect(int port, const char* host = "127.0.0.1");
int startConnect(struct sockaddr* peeraddr);
int startConnect();
// 是否已连接
bool isConnected();
// 返回本地地址
std::string localaddr();
// 返回对端地址
std::string peeraddr();
};
// WebSocketChannel 继承自 SocketChannel
class WebSocketChannel : public SocketChannel {
// 发送文本帧
int send(const std::string& msg, enum ws_opcode opcode = WS_OPCODE_TEXT, bool fin = true);
// 发送二进制帧
int send(const char* buf, int len, enum ws_opcode opcode = WS_OPCODE_BINARY, bool fin = true);
// 分片发送
int send(const char* buf, int len, int fragment, enum ws_opcode opcode = WS_OPCODE_BINARY);
// 关闭
int close();
};
```

123
third_party/libhv/docs/cn/EventLoop.md vendored Executable file
View File

@@ -0,0 +1,123 @@
事件循环类
```c++
class EventLoop {
// 返回底层的loop结构体指针
hloop_t* loop();
// 运行
void run();
// 停止
void stop();
// 暂停
void pause();
// 继续
void resume();
// 设置定时器
TimerID setTimer(int timeout_ms, TimerCallback cb, uint32_t repeat = INFINITE, TimerID timerID = INVALID_TIMER_ID);
// 设置一次性定时器
TimerID setTimeout(int timeout_ms, TimerCallback cb);
// 设置永久性定时器
TimerID setInterval(int interval_ms, TimerCallback cb);
// 杀掉定时器
void killTimer(TimerID timerID);
// 重置定时器
void resetTimer(TimerID timerID, int timeout_ms = 0);
// 返回事件循环所在的线程ID
long tid();
// 是否在事件循环所在线程
bool isInLoopThread();
// 断言在事件循环所在线程
void assertInLoopThread();
// 运行在事件循环里
void runInLoop(Functor fn);
// 队列在事件循环里
void queueInLoop(Functor fn);
// 投递一个事件到事件循环
void postEvent(EventCallback cb);
};
class EventLoopThread {
// 返回事件循环指针
const EventLoopPtr& loop();
// 返回底层的loop结构体指针
hloop_t* hloop();
// 是否运行中
bool isRunning();
/* 开始运行
* wait_thread_started: 是否阻塞等待线程开始
* pre: 线程开始后执行的函数
* post: 线程结束前执行的函数
*/
void start(bool wait_thread_started = true,
Functor pre = Functor(),
Functor post = Functor());
// 停止运行
void stop(bool wait_thread_stopped = false);
// 等待线程退出
void join();
};
class EventLoopThreadPool {
// 获取线程数量
int threadNum();
// 设置线程数量
void setThreadNum(int num);
// 返回下一个事件循环对象
// 支持轮询、随机、最少连接数等负载均衡策略
EventLoopPtr nextLoop(load_balance_e lb = LB_RoundRobin);
// 返回索引的事件循环对象
EventLoopPtr loop(int idx = -1);
// 返回索引的底层loop结构体指针
hloop_t* hloop(int idx = -1);
/* 开始运行
* wait_threads_started: 是否阻塞等待所有线程开始
* pre: 线程开始后执行的函数
* post: 线程结束前执行的函数
*/
void start(bool wait_threads_started = false,
std::function<void(const EventLoopPtr&)> pre = NULL,
std::function<void(const EventLoopPtr&)> post = NULL);
// 停止运行
void stop(bool wait_threads_stopped = false);
// 等待所有线程退出
void join();
};
```
测试代码见:
- [evpp/EventLoop_test.cpp](../../evpp/EventLoop_test.cpp)
- [evpp/EventLoopThread_test.cpp](../../evpp/EventLoopThread_test.cpp)
- [evpp/EventLoopThreadPool_test.cpp](../../evpp/EventLoopThreadPool_test.cpp)

84
third_party/libhv/docs/cn/HttpClient.md vendored Executable file
View File

@@ -0,0 +1,84 @@
HTTP 客户端类
```c++
class HttpClient {
// 设置超时
int setTimeout(int timeout);
// 设置SSL/TLS
int setSslCtx(hssl_ctx_t ssl_ctx);
// 新建SSL/TLS
int newSslCtx(hssl_ctx_opt_t* opt);
// 清除全部请求头部
int clearHeaders();
// 设置请求头部
int setHeader(const char* key, const char* value);
// 删除请求头部
int delHeader(const char* key);
// 获取请求头部
const char* getHeader(const char* key);
// 设置http代理
int setHttpProxy(const char* host, int port);
// 设置https代理
int setHttpsProxy(const char* host, int port);
// 添加不走代理
int addNoProxy(const char* host);
// 同步发送
int send(HttpRequest* req, HttpResponse* resp);
// 异步发送
int sendAsync(HttpRequestPtr req, HttpResponseCallback resp_cb = NULL);
// 关闭连接 (HttpClient对象析构时会自动调用)
int close();
};
namespace requests {
// 同步请求
Response request(Request req);
Response request(http_method method, const char* url, const http_body& body = NoBody, const http_headers& headers = DefaultHeaders);
// 上传文件
Response uploadFile(const char* url, const char* filepath, http_method method = HTTP_POST, const http_headers& headers = DefaultHeaders);
// 通过 `multipart/form-data` 格式上传文件
Response uploadFormFile(const char* url, const char* name, const char* filepath, std::map<std::string, std::string>& params = hv::empty_map, http_method method = HTTP_POST, const http_headers& headers = DefaultHeaders);
// 上传大文件(带上传进度回调)
Response uploadLargeFile(const char* url, const char* filepath, upload_progress_cb progress_cb = NULL, http_method method = HTTP_POST, const http_headers& headers = DefaultHeaders);
// 下载文件 (更详细的断点续传示例代码见`examples/wget.cpp`)
size_t downloadFile(const char* url, const char* filepath, download_progress_cb progress_cb = NULL);
// HEAD 请求
Response head(const char* url, const http_headers& headers = DefaultHeaders);
// GET 请求
Response get(const char* url, const http_headers& headers = DefaultHeaders);
// POST 请求
Response post(const char* url, const http_body& body = NoBody, const http_headers& headers = DefaultHeaders);
// PUT 请求
Response put(const char* url, const http_body& body = NoBody, const http_headers& headers = DefaultHeaders);
// PATCH 请求
Response patch(const char* url, const http_body& body = NoBody, const http_headers& headers = DefaultHeaders);
// DELETE 请求
Response Delete(const char* url, const http_headers& headers = DefaultHeaders);
// 异步请求
int async(Request req, ResponseCallback resp_cb);
}
```
测试代码见 [examples/http_client_test.cpp](../../examples/http_client_test.cpp)

83
third_party/libhv/docs/cn/HttpContext.md vendored Executable file
View File

@@ -0,0 +1,83 @@
```c++
class HttpContext {
/* 获取请求信息 */
// 获取客户端IP
std::string ip();
// 获取客户端端口
int port();
// 获取请求method
http_method method();
// 获取请求url
std::string url();
// 获取请求path
std::string path();
// 获取请求host
std::string host();
// 获取请求头部
const http_headers& headers();
std::string header(const char* key, const std::string& defvalue = hv::empty_string);
// 获取请求参数
const hv::QueryParams& params();
std::string param(const char* key, const std::string& defvalue = hv::empty_string);
// 获取请求cookie
const HttpCookie& cookie(const char* name);
// 获取请求 `Content-Length`
int length();
// 获取请求 `Content-Type`
http_content_type type();
// 判断请求 `Content-Type`
bool is(http_content_type content_type);
// 获取请求body
std::string& body();
// 获取 `application/json` 格式数据
const hv::Json& json();
// 获取 `multipart/form-data` 格式数据
const hv::MultiPart& form();
std::string form(const char* name, const std::string& defvalue = hv::empty_string);
// 获取 `application/x-www-urlencoded` 格式数据
const hv::KeyValue& urlencoded();
std::string urlencoded(const char* key, const std::string& defvalue = hv::empty_string);
// 根据 `Content-Type` 获取对应格式数据
template<typename T>
T get(const char* key, T defvalue = 0);
std::string get(const char* key, const std::string& defvalue = hv::empty_string);
/* 设置响应信息 */
// 设置响应状态码
void setStatus(http_status status);
// 设置响应 `Content-Type`
void setContentType(http_content_type type);
// 设置响应头部
void setHeader(const char* key, const std::string& value);
// 设置响应cookie
void setCookie(const HttpCookie& cookie);
// 设置响应body
void setBody(const std::string& body);
template<typename T>
// 根据 `Content-Type` 设置对应格式数据
void set(const char* key, const T& value);
// 发送
int send();
int send(const std::string& str, http_content_type type = APPLICATION_JSON);
// 发送文本数据
int sendString(const std::string& str);
// 发送二进制数据
int sendData(void* data, int len, bool nocopy = true);
// 发送文件
int sendFile(const char* filepath);
// 发送json数据
template<typename T>
int sendJson(const T& t);
// 重定向
int redirect(const std::string& location, http_status status = HTTP_STATUS_FOUND);
// 主动关闭连接
int close();
};
```

110
third_party/libhv/docs/cn/HttpMessage.md vendored Executable file
View File

@@ -0,0 +1,110 @@
```c++
class HttpMessage {
// 设置/获取头部
void SetHeader(const char* key, const std::string& value);
std::string GetHeader(const char* key, const std::string& defvalue = hv::empty_string);
// 添加/获取cookie
void AddCookie(const HttpCookie& cookie);
const HttpCookie& GetCookie(const std::string& name);
// 设置/获取 `Content-Type`
void SetContentType(http_content_type type);
http_content_type ContentType();
// 获取 `Content-Length`
size_t ContentLength();
// 填充数据
void SetBody(const std::string& body);
// 获取数据
const std::string& Body();
// 解析数据
int ParseBody();
// 填充/获取 `application/json` 格式数据
template<typename T>
int Json(const T& t);
const hv::Json& GetJson();
// 填充/获取 `multipart/form-data` 格式数据
template<typename T>
void SetFormData(const char* name, const T& t);
void SetFormFile(const char* name, const char* filepath);
std::string GetFormData(const char* name, const std::string& defvalue = hv::empty_string);
int SaveFormFile(const char* name, const char* path);
// 填充/获取 `application/x-www-urlencoded` 格式数据
template<typename T>
void SetUrlEncoded(const char* key, const T& t);
std::string GetUrlEncoded(const char* key, const std::string& defvalue = hv::empty_string);
// 根据 `Content-Type` 填充对应格式数据
template<typename T>
void Set(const char* key, const T& value);
// 根据 `Content-Type` 获取对应格式数据
template<typename T>
T Get(const char* key, T defvalue = 0);
// 根据 `Content-Type` 获取对应格式数据并转换成字符串
std::string GetString(const char* key, const std::string& = "");
// 根据 `Content-Type` 获取对应格式数据并转换成Boolean类型
bool GetBool(const char* key, bool defvalue = 0);
// 根据 `Content-Type` 获取对应格式数据并转换成整型
int64_t GetInt(const char* key, int64_t defvalue = 0);
// 根据 `Content-Type` 获取对应格式数据并转换成浮点数
double GetFloat(const char* key, double defvalue = 0);
};
// HttpRequest 继承自 HttpMessage
class HttpRequest : public HttpMessage {
// 设置/获取method
void SetMethod(const char* method);
const char* Method();
// 设置URL
void SetUrl(const char* url);
// 获取URL
const std::string& Url();
// 解析URL
void ParseUrl();
// 获取Host
std::string Host();
// 获取Path
std::string Path();
// 设置/获取参数
template<typename T>
void SetParam(const char* key, const T& t);
std::string GetParam(const char* key, const std::string& defvalue = hv::empty_string);
// 设置代理
void SetProxy(const char* host, int port);
// 设置认证
void SetAuth(const std::string& auth);
void SetBasicAuth(const std::string& username, const std::string& password);
void SetBearerTokenAuth(const std::string& token);
// 设置请求超时
void SetTimeout(int sec);
// 设置连接超时
void SetConnectTimeout(int sec);
// 允许重定向
void AllowRedirect(bool on = true);
// 设置重试
void SetRetry(int count = DEFAULT_HTTP_FAIL_RETRY_COUNT,
int delay = DEFAULT_HTTP_FAIL_RETRY_DELAY);
// 取消
void Cancel();
};
// HttpResponse 继承自 HttpMessage
class HttpResponse : public HttpMessage {
// 状态码
http_status status_code;
// 状态字符串
const char* status_message();
};
```

140
third_party/libhv/docs/cn/HttpServer.md vendored Executable file
View File

@@ -0,0 +1,140 @@
HTTP 服务端类
```c++
// HTTP服务类
class HttpServer {
// 注册HTTP业务类
void registerHttpService(HttpService* service);
// 设置监听主机
void setHost(const char* host = "0.0.0.0");
// 设置监听端口
void setPort(int port = 0, int ssl_port = 0);
// 设置监听文件描述符
void setListenFD(int fd = -1, int ssl_fd = -1);
// 设置IO进程数 (仅`linux`下有效)
void setProcessNum(int num);
// 设置IO线程数
void setThreadNum(int num);
// 设置SSL/TLS
int setSslCtx(hssl_ctx_t ssl_ctx);
// 新建SSL/TLS
int newSslCtx(hssl_ctx_opt_t* opt);
// hooks
// 事件循环开始时执行的回调函数
std::function<void()> onWorkerStart;
// 事件循环结束时执行的回调函数
std::function<void()> onWorkerStop;
// 占用当前线程运行
int run(bool wait = true);
// 不占用当前线程运行
int start();
// 停止服务
int stop();
};
// HTTP业务类
class HttpService {
// 添加静态资源映射
void Static(const char* path, const char* dir);
// 允许跨域访问
void AllowCORS();
// 添加可信代理 (代理白名单)
void AddTrustProxy(const char* host);
// 添加不可信代理 (代理黑名单)
void AddNoProxy(const char* host);
// 开启正向转发代理
void EnableForwardProxy();
// 添加反向代理映射
void Proxy(const char* path, const char* url);
// 添加中间件
void Use(Handler handlerFunc);
// 添加路由处理器
void Handle(const char* httpMethod, const char* relativePath, Handler handlerFunc);
// 添加`HEAD`路由
void HEAD(const char* relativePath, Handler handlerFunc);
// 添加`GET`路由
void GET(const char* relativePath, Handler handlerFunc);
// 添加`POST`路由
void POST(const char* relativePath, Handler handlerFunc);
// 添加`PUT`路由
void PUT(const char* relativePath, Handler handlerFunc);
// 添加`DELETE`路由
void Delete(const char* relativePath, Handler handlerFunc);
// 添加`PATCH`路由
void PATCH(const char* relativePath, Handler handlerFunc);
// 添加任意`HTTP method`路由
void Any(const char* relativePath, Handler handlerFunc);
// 返回注册的路由路径列表
hv::StringList Paths();
// 处理流程:前处理器 -> 中间件 -> 处理器 -> 后处理器
// preprocessor -> middleware -> processor -> postprocessor
// 数据成员
http_handler preprocessor; // 前处理器
http_handlers middleware; // 中间件
http_handler processor; // 处理器
http_handler postprocessor; // 后处理器
std::string base_url; // 基本路径
std::string document_root; // 文档根目录
std::string home_page; // 主页
std::string error_page; // 默认错误页
std::string index_of; // 目录
http_handler errorHandler; // 错误处理器
int proxy_connect_timeout; // 代理连接超时
int proxy_read_timeout; // 代理读超时
int proxy_write_timeout; // 代理写超时
int keepalive_timeout; // 长连接保活超时
int max_file_cache_size; // 文件缓存最大尺寸
int file_cache_stat_interval; // 文件缓存stat间隔查询文件是否修改
int file_cache_expired_time; // 文件缓存过期时间,过期自动释放
int limit_rate; // 下载速度限制
};
/* 几种`handler`处理函数区别说明: */
// 同步`handler`运行在IO线程
typedef std::function<int(HttpRequest* req, HttpResponse* resp)> http_sync_handler;
// 异步`handler`运行在`hv::async`全局线程池,可通过`hv::async::startup`设置线程池属性
typedef std::function<void(const HttpRequestPtr& req, const HttpResponseWriterPtr& writer)> http_async_handler;
// 上下文`handler`运行在IO线程你可以很方便的将`HttpContextPtr`智能指针抛到你的消费者线程/线程池去处理
typedef std::function<int(const HttpContextPtr& ctx)> http_ctx_handler;
// 中间状态`handler`运行在IO线程用来实现大数据量的边接收边处理
typedef std::function<int(const HttpContextPtr& ctx, http_parser_state state, const char* data, size_t size)> http_state_handler;
```
测试代码见 [examples/http_server_test.cpp](../../examples/http_server_test.cpp)

18
third_party/libhv/docs/cn/README.md vendored Executable file
View File

@@ -0,0 +1,18 @@
## c接口
- [hloop: 事件循环](hloop.md)
- [hbase: 基础函数](hbase.md)
- [hlog: 日志](hlog.md)
## c++接口
- [class EventLoop: 事件循环类](EventLoop.md)
- [class Channel: 通道类](Channel.md)
- [class TcpServer: TCP服务端类](TcpServer.md)
- [class TcpClient: TCP客户端类](TcpClient.md)
- [class UdpServer: UDP服务端类](UdpServer.md)
- [class UdpClient: UDP客户端类](UdpClient.md)
- [class HttpServer: HTTP服务端类](HttpServer.md)
- [class HttpClient: HTTP客户端类](HttpClient.md)
- [class WebSocketServer: WebSocket服务端类](WebSocketServer.md)
- [class WebSocketClient: WebSocket客户端类](WebSocketClient.md)

63
third_party/libhv/docs/cn/TcpClient.md vendored Executable file
View File

@@ -0,0 +1,63 @@
TCP 客户端类
```c++
class TcpClient {
// 返回所在的事件循环
const EventLoopPtr& loop();
// 创建套接字
int createsocket(int remote_port, const char* remote_host = "127.0.0.1");
int createsocket(struct sockaddr* remote_addr);
// 绑定端口
int bind(int local_port, const char* local_host = "0.0.0.0");
int bind(struct sockaddr* local_addr);
// 关闭套接字
void closesocket();
// 开始运行
void start(bool wait_threads_started = true);
// 停止运行
void stop(bool wait_threads_stopped = true);
// 是否已连接
bool isConnected();
// 发送
int send(const void* data, int size);
int send(Buffer* buf);
int send(const std::string& str);
// 设置SSL/TLS加密通信
int withTLS(hssl_ctx_opt_t* opt = NULL);
// 设置连接超时
void setConnectTimeout(int ms);
// 设置重连
void setReconnect(reconn_setting_t* setting);
// 是否是重连
bool isReconnect();
// 设置拆包规则
void setUnpack(unpack_setting_t* setting);
// 连接状态回调
std::function<void(const TSocketChannelPtr&)> onConnection;
// 消息回调
std::function<void(const TSocketChannelPtr&, Buffer*)> onMessage;
// 写完成回调
std::function<void(const TSocketChannelPtr&, Buffer*)> onWriteComplete;
};
```
测试代码见 [evpp/TcpClient_test.cpp](../../evpp/TcpClient_test.cpp)

60
third_party/libhv/docs/cn/TcpServer.md vendored Executable file
View File

@@ -0,0 +1,60 @@
TCP 服务端类
```c++
class TcpServer {
// 返回索引的事件循环
EventLoopPtr loop(int idx = -1);
// 创建套接字
int createsocket(int port, const char* host = "0.0.0.0");
// 关闭套接字
void closesocket();
// 设置最大连接数
void setMaxConnectionNum(uint32_t num);
// 设置负载均衡策略
void setLoadBalance(load_balance_e lb);
// 设置线程数
void setThreadNum(int num);
// 开始运行
void start(bool wait_threads_started = true);
// 停止运行
void stop(bool wait_threads_stopped = true);
// 设置SSL/TLS加密通信
int withTLS(hssl_ctx_opt_t* opt = NULL);
// 设置拆包规则
void setUnpack(unpack_setting_t* setting);
// 返回当前连接数
size_t connectionNum();
// 遍历连接
int foreachChannel(std::function<void(const TSocketChannelPtr& channel)> fn);
// 广播消息
int broadcast(const void* data, int size);
int broadcast(const std::string& str);
// 连接到来/断开回调
std::function<void(const TSocketChannelPtr&)> onConnection;
// 消息回调
std::function<void(const TSocketChannelPtr&, Buffer*)> onMessage;
// 写完成回调
std::function<void(const TSocketChannelPtr&, Buffer*)> onWriteComplete;
};
```
测试代码见 [evpp/TcpServer_test.cpp](../../evpp/TcpServer_test.cpp)

42
third_party/libhv/docs/cn/UdpClient.md vendored Executable file
View File

@@ -0,0 +1,42 @@
UDP 客户端类
```c++
class UdpClient {
// 返回所在的事件循环
const EventLoopPtr& loop();
// 创建套接字
int createsocket(int remote_port, const char* remote_host = "127.0.0.1");
// 绑定端口
int bind(int local_port, const char* local_host = "0.0.0.0");
// 关闭套接字
void closesocket();
// 开始运行
void start(bool wait_threads_started = true);
// 停止运行
void stop(bool wait_threads_stopped = true);
// 发送
int sendto(const void* data, int size, struct sockaddr* peeraddr = NULL);
int sendto(Buffer* buf, struct sockaddr* peeraddr = NULL);
int sendto(const std::string& str, struct sockaddr* peeraddr = NULL);
// 设置KCP
void setKcp(kcp_setting_t* setting);
// 消息回调
std::function<void(const TSocketChannelPtr&, Buffer*)> onMessage;
// 写完成回调
std::function<void(const TSocketChannelPtr&, Buffer*)> onWriteComplete;
};
```
测试代码见 [evpp/UdpClient_test.cpp](../../evpp/UdpClient_test.cpp)

39
third_party/libhv/docs/cn/UdpServer.md vendored Executable file
View File

@@ -0,0 +1,39 @@
UDP 服务端类
```c++
class UdpServer {
// 返回所在的事件循环
const EventLoopPtr& loop();
// 创建套接字
int createsocket(int port, const char* host = "0.0.0.0");
// 关闭套接字
void closesocket();
// 开始运行
void start(bool wait_threads_started = true);
// 停止运行
void stop(bool wait_threads_stopped = true);
// 发送
int sendto(const void* data, int size, struct sockaddr* peeraddr = NULL);
int sendto(Buffer* buf, struct sockaddr* peeraddr = NULL);
int sendto(const std::string& str, struct sockaddr* peeraddr = NULL);
// 设置KCP
void setKcp(kcp_setting_t* setting);
// 消息回调
std::function<void(const TSocketChannelPtr&, Buffer*)> onMessage;
// 写完成回调
std::function<void(const TSocketChannelPtr&, Buffer*)> onWriteComplete;
};
```
测试代码见 [evpp/UdpServer_test.cpp](../../evpp/UdpServer_test.cpp)

37
third_party/libhv/docs/cn/WebSocketClient.md vendored Executable file
View File

@@ -0,0 +1,37 @@
WebSocket 客户端类
```c++
class WebSocketClient {
// 打开回调
std::function<void()> onopen;
// 关闭回调
std::function<void()> onclose;
// 消息回调
std::function<void(const std::string& msg)> onmessage;
// 打开
int open(const char* url, const http_headers& headers = DefaultHeaders);
// 关闭
int close();
// 发送
int send(const std::string& msg);
int send(const char* buf, int len, enum ws_opcode opcode = WS_OPCODE_BINARY);
// 设置心跳间隔
void setPingInterval(int ms);
// 设置WebSocket握手阶段的HTTP请求
void setHttpRequest(const HttpRequestPtr& req);
// 获取WebSocket握手阶段的HTTP响应
const HttpResponsePtr& getHttpResponse();
};
```
测试代码见 [examples/websocket_client_test.cpp](../../examples/websocket_client_test.cpp)

30
third_party/libhv/docs/cn/WebSocketServer.md vendored Executable file
View File

@@ -0,0 +1,30 @@
WebSocket 服务端类
```c++
// WebSocketServer 继承自 HttpServer
class WebSocketServer : public HttpServer {
// 注册WebSocket业务类
void registerWebSocketService(WebSocketService* service);
};
// WebSocket业务类
struct WebSocketService {
// 打开回调
std::function<void(const WebSocketChannelPtr&, const HttpRequestPtr&)> onopen;
// 消息回调
std::function<void(const WebSocketChannelPtr&, const std::string&)> onmessage;
// 关闭回调
std::function<void(const WebSocketChannelPtr&)> onclose;
// 心跳间隔
int ping_interval;
};
```
测试代码见 [examples/websocket_server_test.cpp](../../examples/websocket_server_test.cpp)

111
third_party/libhv/docs/cn/hbase.md vendored Executable file
View File

@@ -0,0 +1,111 @@
一些基础函数
```c
/* hv内存分配/释放函数 */
void* hv_malloc(size_t size);
void* hv_realloc(void* oldptr, size_t newsize, size_t oldsize);
void* hv_calloc(size_t nmemb, size_t size);
void* hv_zalloc(size_t size);
void hv_free(void* ptr);
// 使用hv分配内存次数
long hv_alloc_cnt();
// 使用hv释放内存次数
long hv_free_cnt();
/* 字符串操作 */
// 字符串转大写
char* hv_strupper(char* str);
// 字符串转小写
char* hv_strlower(char* str);
// 字符串翻转
char* hv_strreverse(char* str);
// 判断字符串是否以xxx开头
bool hv_strstartswith(const char* str, const char* start);
// 判断字符串是否以xxx结尾
bool hv_strendswith(const char* str, const char* end);
// 判断字符串是否包含xxx
bool hv_strcontains(const char* str, const char* sub);
// 安全的strncpy
char* hv_strncpy(char* dest, const char* src, size_t n);
// 安全的strncat
char* hv_strncat(char* dest, const char* src, size_t n);
// 字符查找
char* hv_strnchr(const char* s, char c, size_t n);
// 查找最后一个点(通常用于提取文件后缀)
#define hv_strrchr_dot(str) strrchr(str, '.')
// 查找最后的路径(通常用于分离目录和文件)
char* hv_strrchr_dir(const char* filepath);
// 获取文件名利用了上面的strrchr_dir
const char* hv_basename(const char* filepath);
// 获取文件后缀利用了上面的strrchr_dot
const char* hv_suffixname(const char* filename);
/* 文件&目录 */
// mkdir -p: 创建目录
int hv_mkdir_p(const char* dir);
// rmdir -p: 删除目录
int hv_rmdir_p(const char* dir);
// 判断路径是否存在
bool hv_exists(const char* path);
// 判断是否是目录
bool hv_isdir(const char* path);
// 判断是否是文件
bool hv_isfile(const char* path);
// 判断是否是链接
bool hv_islink(const char* path);
// 获取文件大小
size_t hv_filesize(const char* filepath);
// 获取可执行文件绝对路径,例如/usr/local/bin/httpd
char* get_executable_path(char* buf, int size);
// 获取可执行文件所在目录,例如/usr/local/bin
char* get_executable_dir(char* buf, int size);
// 获取可执行文件名例如httpd
char* get_executable_file(char* buf, int size);
// 获取运行目录,例如/home/www/html
char* get_run_dir(char* buf, int size);
// 返回一个随机数
int hv_rand(int min, int max);
// 返回一个随机字符串
char* hv_random_string(char *buf, int len);
// 1 y on yes true enable返回true通常用于配置文件
bool hv_getboolean(const char* str);
// 解析size字符串
// 1T2G3M4K5B => ?B
size_t hv_parse_size(const char* str);
// 解析时间字符串
// 1w2d3h4m5s => ?s
time_t hv_parse_time(const char* str);
// 解析url字符串
int hv_parse_url(hurl_t* stURL, const char* strURL);
```
单元测试代码见 [unittest/hbase_test.c](../../unittest/hbase_test.c)

111
third_party/libhv/docs/cn/hlog.md vendored Executable file
View File

@@ -0,0 +1,111 @@
日志
```c
// 标准输出日志
void stdout_logger(int loglevel, const char* buf, int len);
// 标准错误日志
void stderr_logger(int loglevel, const char* buf, int len);
// 文件日志
void file_logger(int loglevel, const char* buf, int len);
// 网络日志定义在event/nlog.h头文件里
// void network_logger(int loglevel, const char* buf, int len);
// 创建日志器
logger_t* logger_create();
// 销毁日志器
void logger_destroy(logger_t* logger);
// 设置日志处理器
void logger_set_handler(logger_t* logger, logger_handler fn);
// 设置日志等级
void logger_set_level(logger_t* logger, int level);
// level = [VERBOSE,DEBUG,INFO,WARN,ERROR,FATAL,SILENT]
void logger_set_level_by_str(logger_t* logger, const char* level);
/*
* 设置日志格式
* format = "%y-%m-%d %H:%M:%S.%z %L %s"
* message = "2020-01-02 03:04:05.067 DEBUG message"
* %y year
* %m month
* %d day
* %H hour
* %M min
* %S sec
* %z ms
* %Z us
* %l First character of level
* %L All characters of level
* %s message
* %% %
*/
void logger_set_format(logger_t* logger, const char* format);
// 设置日志缓存大小
void logger_set_max_bufsize(logger_t* logger, unsigned int bufsize);
// 启用日志颜色
void logger_enable_color(logger_t* logger, int on);
// 日志打印
int logger_print(logger_t* logger, int level, const char* fmt, ...);
// 设置日志文件
void logger_set_file(logger_t* logger, const char* filepath);
// 设置日志文件大小
void logger_set_max_filesize(logger_t* logger, unsigned long long filesize);
// 16, 16M, 16MB
void logger_set_max_filesize_by_str(logger_t* logger, const char* filesize);
// 设置日志文件保留天数
void logger_set_remain_days(logger_t* logger, int days);
// 启用每次写日志文件立即刷新到磁盘即每次都调用fsync会增加IO耗时影响性能
void logger_enable_fsync(logger_t* logger, int on);
// 刷新缓存到磁盘(如对日志文件实时性有必要的,可使用定时器定时刷新到磁盘)
void logger_fsync(logger_t* logger);
// 获取当前日志文件路径
const char* logger_get_cur_file(logger_t* logger);
// hlog: 默认的日志器
logger_t* hv_default_logger();
// 销毁默认的日志器
void hv_destroy_default_logger(void);
// 对默认日志器hlog的一些便利操作宏
#define hlog hv_default_logger()
#define hlog_destory() hv_destroy_default_logger()
/* 禁用hv的默认日志 */
#define hlog_disable() logger_set_level(hlog, LOG_LEVEL_SILENT)
#define hlog_set_file(filepath) logger_set_file(hlog, filepath)
#define hlog_set_level(level) logger_set_level(hlog, level)
#define hlog_set_level_by_str(level) logger_set_level_by_str(hlog, level)
#define hlog_set_handler(fn) logger_set_handler(hlog, fn)
#define hlog_set_format(format) logger_set_format(hlog, format)
#define hlog_set_max_filesize(filesize) logger_set_max_filesize(hlog, filesize)
#define hlog_set_max_filesize_by_str(filesize) logger_set_max_filesize_by_str(hlog, filesize)
#define hlog_set_remain_days(days) logger_set_remain_days(hlog, days)
#define hlog_enable_fsync() logger_enable_fsync(hlog, 1)
#define hlog_disable_fsync() logger_enable_fsync(hlog, 0)
#define hlog_fsync() logger_fsync(hlog)
#define hlog_get_cur_file() logger_get_cur_file(hlog)
#define hlogd(fmt, ...) logger_print(hlog, LOG_LEVEL_DEBUG, fmt " [%s:%d:%s]\n", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
#define hlogi(fmt, ...) logger_print(hlog, LOG_LEVEL_INFO, fmt " [%s:%d:%s]\n", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
#define hlogw(fmt, ...) logger_print(hlog, LOG_LEVEL_WARN, fmt " [%s:%d:%s]\n", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
#define hloge(fmt, ...) logger_print(hlog, LOG_LEVEL_ERROR, fmt " [%s:%d:%s]\n", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
#define hlogf(fmt, ...) logger_print(hlog, LOG_LEVEL_FATAL, fmt " [%s:%d:%s]\n", ## __VA_ARGS__, __FILENAME__, __LINE__, __FUNCTION__)
```
测试代码见 [examples/hloop_test.c](../../examples/hloop_test.c)

646
third_party/libhv/docs/cn/hloop.md vendored Executable file
View File

@@ -0,0 +1,646 @@
事件循环和IO多路复用机制介绍
事件循环是`libevent、libev、libuv、libhv`这类网络库里最核心的概念即在事件循环里处理IO读写事件、定时器事件、自定义事件等各种事件<br>
IO多路复用即在一个IO线程监听多个fd如最早期的`select`、后来的`poll``linux的epoll``windows的iocp``bsd的kqueue``solaris的port`都属于IO多路复用机制。<br>
非阻塞NIO搭配IO多路复用机制就是高并发的钥匙。<br>
`libhv`下的`event`模块正是封装了多种平台的IO多路复用机制提供了统一的事件接口`libhv`的核心模块。<br>
`hloop.h`: 事件循环模块对外头文件。<br>
```c
// 事件结构体
struct hevent_s {
hloop_t* loop; // 事件所属循环
hevent_type_e event_type; // 事件类型
uint64_t event_id; // 事件ID
hevent_cb cb; // 事件回调
void* userdata; // 用户数据
void* privdata; // 私有数据
struct hevent_s* pending_next; // 指向下一个事件,用于实现事件队列
int priority; // 事件优先级
};
// 设置事件ID
#define hevent_set_id(ev, id) ((hevent_t*)(ev))->event_id = id
// 设置事件回调
#define hevent_set_cb(ev, cb) ((hevent_t*)(ev))->cb = cb
// 设置事件优先级
#define hevent_set_priority(ev, prio) ((hevent_t*)(ev))->priority = prio
// 设置事件用户数据
#define hevent_set_userdata(ev, udata) ((hevent_t*)(ev))->userdata = (void*)udata
// 获取事件所属循环
#define hevent_loop(ev) (((hevent_t*)(ev))->loop)
// 获取事件类型
#define hevent_type(ev) (((hevent_t*)(ev))->event_type)
// 获取事件ID
#define hevent_id(ev) (((hevent_t*)(ev))->event_id)
// 获取事件回调
#define hevent_cb(ev) (((hevent_t*)(ev))->cb)
// 获取事件优先级
#define hevent_priority(ev) (((hevent_t*)(ev))->priority)
// 获取事件用户数据
#define hevent_userdata(ev) (((hevent_t*)(ev))->userdata)
// hio_t、htimer_t、hsignal_t、hidle_t皆是继承自hevent_t继承上面的数据成员和函数方法
// 新建事件循环
hloop_t* hloop_new(int flags DEFAULT(HLOOP_FLAG_AUTO_FREE));
// 释放事件循环
void hloop_free(hloop_t** pp);
// 运行事件循环
int hloop_run(hloop_t* loop);
// 停止事件循环
int hloop_stop(hloop_t* loop);
// 暂停事件循环
int hloop_pause(hloop_t* loop);
// 继续事件循环
int hloop_resume(hloop_t* loop);
// 唤醒事件循环
int hloop_wakeup(hloop_t* loop);
// 返回事件循环状态
hloop_status_e hloop_status(hloop_t* loop);
// 更新事件循环里的时间
void hloop_update_time(hloop_t* loop);
// 返回事件循环里记录的时间
uint64_t hloop_now(hloop_t* loop); // s
uint64_t hloop_now_ms(hloop_t* loop); // ms
uint64_t hloop_now_us(hloop_t* loop); // us
// 返回事件循环所在进程ID
long hloop_pid(hloop_t* loop);
// 返回事件循环所在线程ID
long hloop_tid(hloop_t* loop);
// 返回事件循环的循环次数
uint64_t hloop_count(hloop_t* loop);
// 返回事件循环里激活的IO事件数量
uint32_t hloop_nios(hloop_t* loop);
// 返回事件循环里激活的定时器事件数量
uint32_t hloop_ntimers(hloop_t* loop);
// 返回事件循环里激活的空闲事件数量
uint32_t hloop_nidles(hloop_t* loop);
// 返回事件循环里激活的事件数量
uint32_t hloop_nactives(hloop_t* loop);
// 设置事件循环的用户数据
void hloop_set_userdata(hloop_t* loop, void* userdata);
// 获取事件循环的用户数据
void* hloop_userdata(hloop_t* loop);
// 投递事件
void hloop_post_event(hloop_t* loop, hevent_t* ev);
// 添加信号处理
hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo);
// 删除信号处理
void hsignal_del(hsignal_t* sig);
// 添加空闲事件
hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
// 删除空闲事件
void hidle_del(hidle_t* idle);
// 添加超时定时器
htimer_t* htimer_add(hloop_t* loop, htimer_cb cb, uint32_t timeout_ms, uint32_t repeat DEFAULT(INFINITE));
// 添加时间定时器
htimer_t* htimer_add_period(hloop_t* loop, htimer_cb cb,
int8_t minute DEFAULT(0), int8_t hour DEFAULT(-1), int8_t day DEFAULT(-1),
int8_t week DEFAULT(-1), int8_t month DEFAULT(-1), uint32_t repeat DEFAULT(INFINITE));
// 删除定时器
void htimer_del(htimer_t* timer);
// 重置定时器
void htimer_reset(htimer_t* timer, uint32_t timeout_ms DEFAULT(0));
// 返回IO多路复用引擎 (select、poll、epoll、etc.)
const char* hio_engine();
// 获取IO对象
hio_t* hio_get(hloop_t* loop, int fd);
// 添加IO读写事件
int hio_add(hio_t* io, hio_cb cb, int events DEFAULT(HV_READ));
// 删除IO读写事件
int hio_del(hio_t* io, int events DEFAULT(HV_RDWR));
// 将IO对象从当前所属事件循环中剥离
void hio_detach(/*hloop_t* loop,*/ hio_t* io);
// 将IO对象关联到新的事件循环
void hio_attach(hloop_t* loop, hio_t* io);
// hio_detach 和 hio_attach 的示例代码见 examples/multi-thread/one-acceptor-multi-workers.c
/*
void new_conn_event(hevent_t* ev) {
hloop_t* loop = ev->loop;
hio_t* io = (hio_t*)hevent_userdata(ev);
// 关联到新的worker事件循环
hio_attach(loop, io);
}
void on_accpet(hio_t* io) {
// 从acceptor所在事件循环中剥离
hio_detach(io);
// 将新的连接按照负载均衡策略分发到worker线程
hloop_t* worker_loop = get_one_loop();
hevent_t ev;
memset(&ev, 0, sizeof(ev));
ev.loop = worker_loop;
ev.cb = new_conn_event;
ev.userdata = io;
hloop_post_event(worker_loop, &ev);
}
*/
// 判断fd是否存在于事件循环
bool hio_exists(hloop_t* loop, int fd);
// 返回一个唯一标示ID
uint32_t hio_id (hio_t* io);
// 返回文件描述符
int hio_fd (hio_t* io);
// 返回错误码
int hio_error (hio_t* io);
// 返回添加的事件
int hio_events (hio_t* io);
// 获取返回的事件
int hio_revents (hio_t* io);
// 返回IO类型
hio_type_e hio_type (hio_t* io);
// 返回本地地址
struct sockaddr* hio_localaddr(hio_t* io);
// 返回对端地址
struct sockaddr* hio_peeraddr (hio_t* io);
// 设置上下文
void hio_set_context(hio_t* io, void* ctx);
// 获取上下文
void* hio_context(hio_t* io);
// 是否已打开
bool hio_is_opened(hio_t* io);
// 是否已连接
bool hio_is_connected(hio_t* io);
// 是否已关闭
bool hio_is_closed(hio_t* io);
// 设置读缓存
void hio_set_readbuf(hio_t* io, void* buf, size_t len);
// 获取读缓存
hio_readbuf_t* hio_get_readbuf(hio_t* io);
// 设置最大读缓存
void hio_set_max_read_bufsize (hio_t* io, uint32_t size);
// 设置最大写缓存
void hio_set_max_write_bufsize(hio_t* io, uint32_t size);
// 获取当前写缓存大小
size_t hio_write_bufsize(hio_t* io);
// 判断是否写完成
#define hio_write_is_complete(io) (hio_write_bufsize(io) == 0)
// 获取最后读的时间
uint64_t hio_last_read_time(hio_t* io); // ms
// 获取最后写的时间
uint64_t hio_last_write_time(hio_t* io); // ms
// 设置accept回调
void hio_setcb_accept (hio_t* io, haccept_cb accept_cb);
// 设置连接回调
void hio_setcb_connect (hio_t* io, hconnect_cb connect_cb);
// 设置读回调
void hio_setcb_read (hio_t* io, hread_cb read_cb);
// 设置写回调
void hio_setcb_write (hio_t* io, hwrite_cb write_cb);
// 设置关闭回调
void hio_setcb_close (hio_t* io, hclose_cb close_cb);
// 获取accept回调
haccept_cb hio_getcb_accept(hio_t* io);
// 获取连接回调
hconnect_cb hio_getcb_connect(hio_t* io);
// 获取读回调
hread_cb hio_getcb_read(hio_t* io);
// 获取写回调
hwrite_cb hio_getcb_write(hio_t* io);
// 获取关闭回调
hclose_cb hio_getcb_close(hio_t* io);
// 开启SSL/TLS加密通信
int hio_enable_ssl(hio_t* io);
// 是否SSL/TLS加密通信
bool hio_is_ssl(hio_t* io);
// 设置SSL
int hio_set_ssl (hio_t* io, hssl_t ssl);
// 设置SSL_CTX
int hio_set_ssl_ctx(hio_t* io, hssl_ctx_t ssl_ctx);
// 新建SSL_CTX
int hio_new_ssl_ctx(hio_t* io, hssl_ctx_opt_t* opt);
// 获取SSL
hssl_t hio_get_ssl(hio_t* io);
// 获取SSL_CTX
hssl_ctx_t hio_get_ssl_ctx(hio_t* io);
// 设置主机名
int hio_set_hostname(hio_t* io, const char* hostname);
// 获取主机名
const char* hio_get_hostname(hio_t* io);
// 设置连接超时
void hio_set_connect_timeout(hio_t* io, int timeout_ms DEFAULT(HIO_DEFAULT_CONNECT_TIMEOUT));
// 设置关闭超时 (说明:非阻塞写队列非空时,需要等待写完成再关闭)
void hio_set_close_timeout(hio_t* io, int timeout_ms DEFAULT(HIO_DEFAULT_CLOSE_TIMEOUT));
// 设置读超时 (一段时间没有数据到来便自动关闭连接)
void hio_set_read_timeout(hio_t* io, int timeout_ms);
// 设置写超时 (一段时间没有数据发送便自动关闭连接)
void hio_set_write_timeout(hio_t* io, int timeout_ms);
// 设置keepalive超时 (一段时间没有数据收发便自动关闭连接)
void hio_set_keepalive_timeout(hio_t* io, int timeout_ms DEFAULT(HIO_DEFAULT_KEEPALIVE_TIMEOUT));
// 设置心跳 (定时发送心跳包)
typedef void (*hio_send_heartbeat_fn)(hio_t* io);
void hio_set_heartbeat(hio_t* io, int interval_ms, hio_send_heartbeat_fn fn);
// 接收连接
// hio_add(io, HV_READ) => accept => haccept_cb
int hio_accept (hio_t* io);
// 连接
// connect => hio_add(io, HV_WRITE) => hconnect_cb
int hio_connect(hio_t* io);
// 读
// hio_add(io, HV_READ) => read => hread_cb
int hio_read (hio_t* io);
// 开始读
#define hio_read_start(io) hio_read(io)
// 停止读
#define hio_read_stop(io) hio_del(io, HV_READ)
// 读一次
// hio_read_start => hread_cb => hio_read_stop
int hio_read_once (hio_t* io);
// 读取直到指定长度
// hio_read_once => hread_cb(len)
int hio_read_until_length(hio_t* io, unsigned int len);
// 读取直到遇到分隔符
// hio_read_once => hread_cb(...delim)
int hio_read_until_delim (hio_t* io, unsigned char delim);
// 读取一行
#define hio_readline(io) hio_read_until_delim(io, '\n')
// 读取字符串
#define hio_readstring(io) hio_read_until_delim(io, '\0')
// 读取N个字节
#define hio_readbytes(io, len) hio_read_until_length(io, len)
#define hio_read_until(io, len) hio_read_until_length(io, len)
// 写
// hio_try_write => hio_add(io, HV_WRITE) => write => hwrite_cb
int hio_write (hio_t* io, const void* buf, size_t len);
// 关闭
// hio_del(io, HV_RDWR) => close => hclose_cb
int hio_close (hio_t* io);
// 异步关闭 (投递一个close事件)
// NOTE: hloop_post_event(hio_close_event)
int hio_close_async(hio_t* io);
//------------------高等级的接口-------------------------------------------
// 读
// hio_get -> hio_set_readbuf -> hio_setcb_read -> hio_read
hio_t* hread (hloop_t* loop, int fd, void* buf, size_t len, hread_cb read_cb);
// 写
// hio_get -> hio_setcb_write -> hio_write
hio_t* hwrite (hloop_t* loop, int fd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
// 关闭
// hio_get -> hio_close
void hclose (hloop_t* loop, int fd);
// tcp
// 接收连接
// hio_get -> hio_setcb_accept -> hio_accept
hio_t* haccept (hloop_t* loop, int listenfd, haccept_cb accept_cb);
// 连接
// hio_get -> hio_setcb_connect -> hio_connect
hio_t* hconnect (hloop_t* loop, int connfd, hconnect_cb connect_cb);
// 接收
// hio_get -> hio_set_readbuf -> hio_setcb_read -> hio_read
hio_t* hrecv (hloop_t* loop, int connfd, void* buf, size_t len, hread_cb read_cb);
// 发送
// hio_get -> hio_setcb_write -> hio_write
hio_t* hsend (hloop_t* loop, int connfd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
// udp
// 设置IO类型
void hio_set_type(hio_t* io, hio_type_e type);
// 设置本地地址
void hio_set_localaddr(hio_t* io, struct sockaddr* addr, int addrlen);
// 设置对端地址
void hio_set_peeraddr (hio_t* io, struct sockaddr* addr, int addrlen);
// 接收
// hio_get -> hio_set_readbuf -> hio_setcb_read -> hio_read
hio_t* hrecvfrom (hloop_t* loop, int sockfd, void* buf, size_t len, hread_cb read_cb);
// 发送
// hio_get -> hio_setcb_write -> hio_write
hio_t* hsendto (hloop_t* loop, int sockfd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
//-----------------顶层的接口---------------------------------------------
// 创建socket套接字返回IO对象
// @hio_create_socket: socket -> bind -> listen
// sockaddr_set_ipport -> socket -> hio_get(loop, sockfd) ->
// side == HIO_SERVER_SIDE ? bind ->
// type & HIO_TYPE_SOCK_STREAM ? listen ->
hio_t* hio_create_socket(hloop_t* loop, const char* host, int port,
hio_type_e type DEFAULT(HIO_TYPE_TCP),
hio_side_e side DEFAULT(HIO_SERVER_SIDE));
// @tcp_server: hio_create_socket(loop, host, port, HIO_TYPE_TCP, HIO_SERVER_SIDE) -> hio_setcb_accept -> hio_accept
// 创建TCP服务示例代码见 examples/tcp_echo_server.c
hio_t* hloop_create_tcp_server (hloop_t* loop, const char* host, int port, haccept_cb accept_cb);
// @tcp_client: hio_create_socket(loop, host, port, HIO_TYPE_TCP, HIO_CLIENT_SIDE) -> hio_setcb_connect -> hio_setcb_close -> hio_connect
// 创建TCP客户端示例代码见 examples/nc.c
hio_t* hloop_create_tcp_client (hloop_t* loop, const char* host, int port, hconnect_cb connect_cb, hclose_cb close_cb);
// @ssl_server: hio_create_socket(loop, host, port, HIO_TYPE_SSL, HIO_SERVER_SIDE) -> hio_setcb_accept -> hio_accept
// 创建SSL服务端示例代码见 examples/tcp_echo_server.c => #define TEST_SSL 1
hio_t* hloop_create_ssl_server (hloop_t* loop, const char* host, int port, haccept_cb accept_cb);
// @ssl_client: hio_create_socket(loop, host, port, HIO_TYPE_SSL, HIO_CLIENT_SIDE) -> hio_setcb_connect -> hio_setcb_close -> hio_connect
// 创建SSL客户端示例代码见 examples/nc.c => #define TEST_SSL 1
hio_t* hloop_create_ssl_client (hloop_t* loop, const char* host, int port, hconnect_cb connect_cb, hclose_cb close_cb);
// @udp_server: hio_create_socket(loop, host, port, HIO_TYPE_UDP, HIO_SERVER_SIDE)
// 创建UDP服务端示例代码见 examples/udp_echo_server.c
hio_t* hloop_create_udp_server (hloop_t* loop, const char* host, int port);
// @udp_server: hio_create_socket(loop, host, port, HIO_TYPE_UDP, HIO_CLIENT_SIDE)
// 创建UDP客户端示例代码见 examples/nc.c
hio_t* hloop_create_udp_client (hloop_t* loop, const char* host, int port);
//-----------------pipe---------------------------------------------
// 创建pipe示例代码见 examples/pipe_test.c
int hio_create_pipe(hloop_t* loop, hio_t* pipeio[2]);
//-----------------转发---------------------------------------------
// hio_read(io)
// hio_read(io->upstream_io)
void hio_read_upstream(hio_t* io);
// on_write(io) -> hio_write_is_complete(io) -> hio_read(io->upstream_io)
void hio_read_upstream_on_write_complete(hio_t* io, const void* buf, int writebytes);
// hio_write(io->upstream_io, buf, bytes)
void hio_write_upstream(hio_t* io, void* buf, int bytes);
// hio_close(io->upstream_io)
void hio_close_upstream(hio_t* io);
// io1->upstream_io = io2;
// io2->upstream_io = io1;
// 建立转发,示例代码见 examples/socks5_proxy_server.c
void hio_setup_upstream(hio_t* io1, hio_t* io2);
// @return io->upstream_io
hio_t* hio_get_upstream(hio_t* io);
// @tcp_upstream: hio_create_socket -> hio_setup_upstream -> hio_connect -> on_connect -> hio_read_upstream
// @return upstream_io
// 建立TCP转发示例代码见 examples/tcp_proxy_server.c
hio_t* hio_setup_tcp_upstream(hio_t* io, const char* host, int port, int ssl DEFAULT(0));
// 建立SSL转发
#define hio_setup_ssl_upstream(io, host, port) hio_setup_tcp_upstream(io, host, port, 1)
// @udp_upstream: hio_create_socket -> hio_setup_upstream -> hio_read_upstream
// @return upstream_io
// 建立UDP转发示例代码见 examples/udp_proxy_server.c
hio_t* hio_setup_udp_upstream(hio_t* io, const char* host, int port);
//-----------------拆包---------------------------------------------
// 拆包模式
typedef enum {
UNPACK_MODE_NONE = 0,
UNPACK_BY_FIXED_LENGTH = 1, // 固定长度拆包,不建议
UNPACK_BY_DELIMITER = 2, // 根据分隔符拆包,适用于文本协议
UNPACK_BY_LENGTH_FIELD = 3, // 根据头部长度字段拆包,适用于二进制协议
} unpack_mode_e;
// 拆包设置
typedef struct unpack_setting_s {
unpack_mode_e mode; // 拆包模式
unsigned int package_max_length; // 最大的包长
union {
// UNPACK_BY_FIXED_LENGTH: 固定长度拆包设置
struct {
unsigned int fixed_length; // 固定长度
};
// UNPACK_BY_DELIMITER: 分隔符拆包设置
struct {
unsigned char delimiter[PACKAGE_MAX_DELIMITER_BYTES]; // 分隔符
unsigned short delimiter_bytes; // 分隔符所占字节数
};
/*
* UNPACK_BY_LENGTH_FIELD: 头部长度字段拆包设置
*
* 包长 = 头部长度 + 数据长度 + 调整长度
* package_len = head_len + body_len + length_adjustment
*
* if (length_field_coding == ENCODE_BY_VARINT) head_len = body_offset + varint_bytes - length_field_bytes;
* else head_len = body_offset;
*
* 注意:头部长度字段的值仅代表数据长度,不包括头部本身长度,
* 如果你的头部长度字段代表总包长那么应该将length_adjustment设置为负的头部长度
* length_field stores body length, exclude head length,
* if length_field = head_len + body_len, then length_adjustment should be set to -head_len.
*
*/
struct {
unsigned short body_offset; // 到数据的偏移,通常等于头部长度
unsigned short length_field_offset; // 长度字段偏移
unsigned short length_field_bytes; // 长度字段所占字节数
short length_adjustment; // 调整长度
unpack_coding_e length_field_coding; // 长度字段编码方式
};
};
} unpack_setting_t;
/*
* 拆包示例代码见 examples/jsonrpc examples/protorpc
*
* 注意多个IO对象的unpack_setting_t可能是一样的所有hio_t里仅保存了unpack_setting_t的指针
* unpack_setting_t的生命周期应该被调用者所保证不应该使用局部变量。
*/
// 设置拆包
void hio_set_unpack(hio_t* io, unpack_setting_t* setting);
// 取消拆包设置
void hio_unset_unpack(hio_t* io);
// 拆包设置示例:
/*
// FTP协议通过\r\n分割符拆包
unpack_setting_t ftp_unpack_setting;
memset(&ftp_unpack_setting, 0, sizeof(unpack_setting_t));
ftp_unpack_setting.package_max_length = DEFAULT_PACKAGE_MAX_LENGTH;
ftp_unpack_setting.mode = UNPACK_BY_DELIMITER;
ftp_unpack_setting.delimiter[0] = '\r';
ftp_unpack_setting.delimiter[1] = '\n';
ftp_unpack_setting.delimiter_bytes = 2;
// MQTT协议通过头部长度字段拆包头部长度字段使用了varint编码
unpack_setting_t mqtt_unpack_setting = {
.mode = UNPACK_BY_LENGTH_FIELD,
.package_max_length = DEFAULT_PACKAGE_MAX_LENGTH,
.body_offset = 2,
.length_field_offset = 1,
.length_field_bytes = 1,
.length_field_coding = ENCODE_BY_VARINT,
};
*/
//-----------------重连----------------------------------------
// 重连设置
typedef struct reconn_setting_s {
uint32_t min_delay; // ms 重连最小延时
uint32_t max_delay; // ms 重连最大延时
uint32_t cur_delay; // ms 当前延时
/*
* @delay_policy: 延时策略
* 0: fixed 固定延时
* min_delay=3s => 3,3,3...
* 1: linear 线性增长延时
* min_delay=3s max_delay=10s => 3,6,9,10,10...
* other: exponential 指数增长延时
* min_delay=3s max_delay=60s delay_policy=2 => 3,6,12,24,48,60,60...
*/
uint32_t delay_policy; // 延时策略
uint32_t max_retry_cnt; // 最大重试次数
uint32_t cur_retry_cnt; // 当前重试次数
} reconn_setting_t;
// 重连设置初始化
void reconn_setting_init(reconn_setting_t* reconn);
// 重连设置重置
void reconn_setting_reset(reconn_setting_t* reconn);
// 增加重试次数并判断是否未超过最大重试次数
bool reconn_setting_can_retry(reconn_setting_t* reconn);
// 计算当前重连延时
uint32_t reconn_setting_calc_delay(reconn_setting_t* reconn);
//-----------------负载均衡-------------------------------------
// 负载均衡策略枚举
typedef enum {
LB_RoundRobin, // 轮询
LB_Random, // 随机
LB_LeastConnections,// 最少连接数
LB_IpHash, // IP hash
LB_UrlHash, // URL hash
} load_balance_e;
//-----------------可靠UDP---------------------------------------------
// 关闭可靠UDP
int hio_close_rudp(hio_t* io, struct sockaddr* peeraddr DEFAULT(NULL));
// KCP设置
typedef struct kcp_setting_s {
// ikcp_create(conv, ...)
unsigned int conv;
// ikcp_nodelay(kcp, nodelay, interval, fastresend, nocwnd)
int nodelay;
int interval;
int fastresend;
int nocwnd;
// ikcp_wndsize(kcp, sndwnd, rcvwnd)
int sndwnd;
int rcvwnd;
// ikcp_setmtu(kcp, mtu)
int mtu;
// ikcp_update
int update_interval;
} kcp_setting_t;
// KCP 正常模式
HV_INLINE void kcp_setting_init_with_normal_mode(kcp_setting_t* setting);
// KCP fast模式
void kcp_setting_init_with_fast_mode(kcp_setting_t* setting);
// KCP fast2模式
void kcp_setting_init_with_fast2_mode(kcp_setting_t* setting);
// KCP fast3模式
void kcp_setting_init_with_fast3_mode(kcp_setting_t* setting);
// 设置KCP示例代码见 examples/udp_echo_server.c => #define TEST_KCP 1
int hio_set_kcp(hio_t* io, kcp_setting_t* setting DEFAULT(NULL));
```
示例代码:
- 事件循环: [examples/hloop_test.c](../../examples/hloop_test.c)
- 定时器: [examples/htimer_test.c](../../examples/htimer_test.c)
- TCP回显服务: [examples/tcp_echo_server.c](../../examples/tcp_echo_server.c)
- TCP聊天服务: [examples/tcp_chat_server.c](../../examples/tcp_chat_server.c)
- TCP代理服务: [examples/tcp_proxy_server.c](../../examples/tcp_proxy_server.c)
- TCP客户端: [examples/tcp_client_test.c](../../examples/tcp_client_test.c)
- UDP回显服务: [examples/udp_echo_server.c](../../examples/udp_echo_server.c)
- UDP代理服务: [examples/udp_proxy_server.c](../../examples/udp_proxy_server.c)
- 网络客户端: [examples/nc](../../examples/nc.c)
- SOCKS5代理服务: [examples/socks5_proxy_server.c](../../examples/socks5_proxy_server.c)
- HTTP服务: [examples/tinyhttpd.c](../../examples/tinyhttpd.c)
- HTTP代理服务: [examples/tinyproxyd.c](../../examples/tinyproxyd.c)
- jsonRPC示例: [examples/jsonrpc](../../examples/jsonrpc)
- protobufRPC示例: [examples/protorpc](../../examples/protorpc)
多进程/多线程模式示例代码:
- 多accept进程模式: [examples/multi-thread/multi-acceptor-processes.c](../../examples/multi-thread/multi-acceptor-processes.c)
- 多accept线程模式: [examples/multi-thread/multi-acceptor-threads.c](../../examples/multi-thread/multi-acceptor-threads.c)
- 一个accept线程+多worker线程: [examples/multi-thread/one-acceptor-multi-workers.c](../../examples/multi-thread/one-acceptor-multi-workers.c)