From 3564a4f7abe77bdbd8428c8cc972ae85517190ed Mon Sep 17 00:00:00 2001 From: ithewei Date: Wed, 24 Apr 2024 00:23:44 +0800 Subject: [PATCH] support pipe --- Makefile | 5 +++- README-CN.md | 3 ++- README.md | 3 ++- docs/API.md | 1 + docs/cn/hloop.md | 4 ++++ event/hloop.c | 22 ++++++++++++++++++ event/hloop.h | 5 ++++ event/nio.c | 2 ++ examples/CMakeLists.txt | 4 ++++ examples/README.md | 2 ++ examples/pipe_test.c | 51 +++++++++++++++++++++++++++++++++++++++++ 11 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 examples/pipe_test.c diff --git a/Makefile b/Makefile index 6b216afed..1455d3504 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ default: all all: libhv examples @echo "make all done, please enjoy libhv." -examples: hmain_test htimer_test hloop_test \ +examples: hmain_test htimer_test hloop_test pipe_test \ nc nmap tinyhttpd tinyproxyd httpd curl wget wrk consul \ tcp_client_test \ tcp_echo_server \ @@ -111,6 +111,9 @@ htimer_test: prepare hloop_test: prepare $(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/hloop_test.c" +pipe_test: prepare + $(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/pipe_test.c" + tcp_client_test: prepare $(MAKEF) TARGET=$@ SRCDIRS="$(CORE_SRCDIRS)" SRCS="examples/tcp_client_test.c" diff --git a/README-CN.md b/README-CN.md index 8317a66e8..7ed65727e 100644 --- a/README-CN.md +++ b/README-CN.md @@ -402,6 +402,7 @@ int main(int argc, char** argv) { ### c版本 - 事件循环: [examples/hloop_test.c](examples/hloop_test.c) - 定时器: [examples/htimer_test.c](examples/htimer_test.c) +- pipe示例: [examples/pipe_test.c](examples/pipe_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) @@ -429,7 +430,6 @@ int main(int argc, char** argv) { - HTTP客户端: [examples/http_client_test.cpp](examples/http_client_test.cpp) - WebSocket服务端: [examples/websocket_server_test.cpp](examples/websocket_server_test.cpp) - WebSocket客户端: [examples/websocket_client_test.cpp](examples/websocket_client_test.cpp) -- kcptun隧道: [examples/kcptun](examples/kcptun) - protobufRPC示例: [examples/protorpc](examples/protorpc) - Qt中使用libhv示例: [hv-projects/QtDemo](https://github.com/hv-projects/QtDemo) @@ -441,6 +441,7 @@ int main(int argc, char** argv) { - URL请求工具: [examples/curl](examples/curl.cpp) - 文件下载工具: [examples/wget](examples/wget.cpp) - 服务注册与发现: [examples/consul](examples/consul) +- kcptun隧道: [examples/kcptun](examples/kcptun) ## 🥇 性能测试 diff --git a/README.md b/README.md index bd1a3f0c3..c370552aa 100644 --- a/README.md +++ b/README.md @@ -342,6 +342,7 @@ int main(int argc, char** argv) { ### c version - [examples/hloop_test.c](examples/hloop_test.c) - [examples/htimer_test.c](examples/htimer_test.c) +- [examples/pipe_test.c](examples/pipe_test.c) - [examples/tcp_echo_server.c](examples/tcp_echo_server.c) - [examples/tcp_chat_server.c](examples/tcp_chat_server.c) - [examples/tcp_proxy_server.c](examples/tcp_proxy_server.c) @@ -369,7 +370,6 @@ int main(int argc, char** argv) { - [examples/http_client_test.cpp](examples/http_client_test.cpp) - [examples/websocket_server_test.cpp](examples/websocket_server_test.cpp) - [examples/websocket_client_test.cpp](examples/websocket_client_test.cpp) -- [examples/kcptun](examples/kcptun) - [examples/protorpc](examples/protorpc) - [hv-projects/QtDemo](https://github.com/hv-projects/QtDemo) @@ -381,6 +381,7 @@ int main(int argc, char** argv) { - [examples/curl](examples/curl.cpp) - [examples/wget](examples/wget.cpp) - [examples/consul](examples/consul) +- [examples/kcptun](examples/kcptun) ## 🥇 Benchmark ### `pingpong echo-servers` diff --git a/docs/API.md b/docs/API.md index 043d496bc..e8bae597d 100644 --- a/docs/API.md +++ b/docs/API.md @@ -470,6 +470,7 @@ - hio_setup_ssl_upstream - hio_setup_udp_upstream - hio_create_socket +- hio_create_pipe - hio_context - hio_set_context - htimer_add diff --git a/docs/cn/hloop.md b/docs/cn/hloop.md index ebaf84ab0..4f72b75c8 100644 --- a/docs/cn/hloop.md +++ b/docs/cn/hloop.md @@ -416,6 +416,10 @@ hio_t* hloop_create_udp_server (hloop_t* loop, const char* host, int port); // 创建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) diff --git a/event/hloop.c b/event/hloop.c index 3937730b1..5ee7a4969 100644 --- a/event/hloop.c +++ b/event/hloop.c @@ -1025,3 +1025,25 @@ hio_t* hloop_create_udp_server(hloop_t* loop, const char* host, int port) { hio_t* hloop_create_udp_client(hloop_t* loop, const char* host, int port) { return hio_create_socket(loop, host, port, HIO_TYPE_UDP, HIO_CLIENT_SIDE); } + +int hio_create_pipe(hloop_t* loop, hio_t* pipeio[2]) { + int pipefd[2]; + hio_type_e type = HIO_TYPE_PIPE; +#if defined(OS_UNIX) && HAVE_PIPE + if (pipe(pipefd) != 0) { + hloge("pipe create failed!"); + return -1; + } +#else + if (Socketpair(AF_INET, SOCK_STREAM, 0, pipefd) != 0) { + hloge("socketpair create failed!"); + return -1; + } + type = HIO_TYPE_TCP; +#endif + pipeio[0] = hio_get(loop, pipefd[0]); + pipeio[1] = hio_get(loop, pipefd[1]); + pipeio[0]->io_type = type; + pipeio[1]->io_type = type; + return 0; +} diff --git a/event/hloop.h b/event/hloop.h index 5cc58366c..d2587f9e3 100644 --- a/event/hloop.h +++ b/event/hloop.h @@ -94,6 +94,7 @@ typedef enum { HIO_TYPE_STDIO = 0x0000000F, HIO_TYPE_FILE = 0x00000010, + HIO_TYPE_PIPE = 0x00000020, HIO_TYPE_IP = 0x00000100, HIO_TYPE_SOCK_RAW = 0x00000F00, @@ -436,6 +437,10 @@ HV_EXPORT hio_t* hloop_create_udp_server (hloop_t* loop, const char* host, int p // @see examples/nc.c HV_EXPORT hio_t* hloop_create_udp_client (hloop_t* loop, const char* host, int port); +//-----------------pipe--------------------------------------------- +// @see examples/pipe_test.c +HV_EXPORT int hio_create_pipe(hloop_t* loop, hio_t* pipeio[2]); + //-----------------upstream--------------------------------------------- // hio_read(io) // hio_read(io->upstream_io) diff --git a/event/nio.c b/event/nio.c index 14f43e2d7..b6d7a27f7 100644 --- a/event/nio.c +++ b/event/nio.c @@ -600,6 +600,8 @@ int hio_close (hio_t* io) { SAFE_FREE(io->hostname); if (io->io_type & HIO_TYPE_SOCKET) { closesocket(io->fd); + } else if (io->io_type == HIO_TYPE_PIPE) { + close(io->fd); } return 0; } diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e02eb46de..a216514e8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,6 +1,7 @@ list(APPEND EXAMPLES hloop_test htimer_test + pipe_test nc tinyhttpd tinyproxyd @@ -23,6 +24,9 @@ target_link_libraries(hloop_test ${HV_LIBRARIES}) add_executable(htimer_test htimer_test.c) target_link_libraries(htimer_test ${HV_LIBRARIES}) +add_executable(pipe_test pipe_test.c) +target_link_libraries(pipe_test ${HV_LIBRARIES}) + add_executable(nc nc.c) target_link_libraries(nc ${HV_LIBRARIES}) diff --git a/examples/README.md b/examples/README.md index 273f2e3cc..c10f18fbe 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,6 +5,7 @@ ├── consul/ consul服务注册与发现 ├── httpd/ HTTP服务端 ├── jsonrpc/ json RPC示例 +├── kcptun/ kcp隧道 ├── mqtt/ MQTT发布订阅示例 ├── multi-thread/ 多线程网络编程示例 ├── nmap/ 网络扫描工具 @@ -16,6 +17,7 @@ ├── http_client_test.c HTTP客户端测试代码 ├── http_server_test.c HTTP服务端测试代码 ├── nc.c 网络连接工具 +├── pipe_test.c pipe示例代码 ├── socks5_proxy_server.c SOCKS5代理服务 ├── tcp_chat_server.c TCP聊天服务 ├── tcp_echo_server.c TCP回显服务 diff --git a/examples/pipe_test.c b/examples/pipe_test.c new file mode 100644 index 000000000..cdcb6ce11 --- /dev/null +++ b/examples/pipe_test.c @@ -0,0 +1,51 @@ +/* + * hio_create_pipe test + * + * @build make examples + * @test bin/pipe_test + * + */ + +#include "hloop.h" +#include "htime.h" + +static hio_t* pipeio[2] = { NULL, NULL }; + +static void on_read(hio_t* io, void* buf, int readbytes) { + printf("< %.*s\n", readbytes, (char*)buf); +} + +static void on_timer_write(htimer_t* timer) { + char str[DATETIME_FMT_BUFLEN] = {0}; + datetime_t dt = datetime_now(); + datetime_fmt(&dt, str); + hio_write(pipeio[1], str, strlen(str)); +} + +static void on_timer_stop(htimer_t* timer) { + hio_close(pipeio[0]); + hio_close(pipeio[1]); + hloop_stop(hevent_loop(timer)); +} + +int main(int argc, char** argv) { + hloop_t* loop = hloop_new(0); + + int ret = hio_create_pipe(loop, pipeio); + if (ret != 0) { + printf("hio_create_pipe failed!\n"); + return -10; + } + printf("pipefd %d<=>%d\n", hio_fd(pipeio[0]), hio_fd(pipeio[1])); + + hio_setcb_read(pipeio[0], on_read); + hio_read(pipeio[0]); + + htimer_add(loop, on_timer_write, 1000, INFINITE); + + htimer_add(loop, on_timer_stop, 10000, 1); + + hloop_run(loop); + hloop_free(&loop); + return 0; +}