emsApplication/3rdPartner/libhv/docs/cn/hloop.md

647 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

事件循环和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)