ithewei 4 years ago
parent
commit
648183cec5

+ 154 - 17
README-CN.md

@@ -62,8 +62,9 @@ vcpkg install libhv
 xrepo install libhv
 ```
 
-## ⚡️ 入门与体验
+## ⚡️ 快速入门
 
+### 体验
 运行脚本`./getting_started.sh`:
 
 ```shell
@@ -100,11 +101,143 @@ bin/curl -v localhost:8080/test -F 'bool=1 int=123 float=3.14 string=hello'
 bin/curl -v -X DELETE localhost:8080/group/test/user/123
 ```
 
+### TCP
+#### TCP服务端
+**c版本**: [examples/tcp_echo_server.c](examples/tcp_echo_server.c)
+```c
+#include "hloop.h"
+
+static void on_close(hio_t* io) {
+    printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
+}
+
+static void on_recv(hio_t* io, void* buf, int readbytes) {
+    // echo
+    hio_write(io, buf, readbytes);
+}
+
+static void on_accept(hio_t* io) {
+    hio_setcb_close(io, on_close);
+    hio_setcb_read(io, on_recv);
+    hio_read(io);
+}
+
+int main() {
+    int port = 1234;
+    hloop_t* loop = hloop_new(0);
+    hio_t* listenio = hloop_create_tcp_server(loop, "0.0.0.0", port, on_accept);
+    if (listenio == NULL) {
+        return -1;
+    }
+    hloop_run(loop);
+    hloop_free(&loop);
+    return 0;
+}
+```
+
+**c++版本**: [evpp/TcpServer_test.cpp](evpp/TcpServer_test.cpp)
+```c++
+#include "TcpServer.h"
+using namespace hv;
+
+int main() {
+    int port = 1234;
+    TcpServer srv;
+    int listenfd = srv.createsocket(port);
+    if (listenfd < 0) {
+        return -1;
+    }
+    printf("server listen on port %d, listenfd=%d ...\n", port, listenfd);
+    srv.onConnection = [](const SocketChannelPtr& channel) {
+        std::string peeraddr = channel->peeraddr();
+        if (channel->isConnected()) {
+            printf("%s connected! connfd=%d\n", peeraddr.c_str(), channel->fd());
+        } else {
+            printf("%s disconnected! connfd=%d\n", peeraddr.c_str(), channel->fd());
+        }
+    };
+    srv.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
+        // echo
+        channel->write(buf);
+    };
+    srv.setThreadNum(4);
+    srv.start();
+
+    while (1) hv_sleep(1);
+    return 0;
+}
+```
+
+#### TCP客户端
+**c版本**: [examples/nc.c](examples/nc.c)
+```c
+#include "hloop.h"
+
+static void on_close(hio_t* io) {
+    printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
+}
+
+static void on_recv(hio_t* io, void* buf, int readbytes) {
+    printf("< %.*s\n", readbytes, (char*)buf);
+}
+
+static void on_connect(hio_t* io) {
+    hio_setcb_close(io, on_close);
+    hio_setcb_read(io, on_recv);
+    hio_read(io);
+
+    hio_write(io, "hello", 5);
+}
+
+int main() {
+    int port = 1234;
+    hloop_t* loop = hloop_new(0);
+    hio_t* connio = hloop_create_tcp_client(loop, "127.0.0.1", port, on_connect);
+    if (connio == NULL) {
+        return -1;
+    }
+    hloop_run(loop);
+    hloop_free(&loop);
+    return 0;
+}
+```
+
+**c++版本**: [evpp/TcpClient_test.cpp](evpp/TcpClient_test.cpp)
+```c++
+#include "TcpClient.h"
+using namespace hv;
+
+int main() {
+    int port = 1234;
+    TcpClient cli;
+    int connfd = cli.createsocket(port);
+    if (connfd < 0) {
+        return -1;
+    }
+    cli.onConnection = [](const SocketChannelPtr& channel) {
+        std::string peeraddr = channel->peeraddr();
+        if (channel->isConnected()) {
+            printf("connected to %s! connfd=%d\n", peeraddr.c_str(), channel->fd());
+            channel->write("hello");
+        } else {
+            printf("disconnected to %s! connfd=%d\n", peeraddr.c_str(), channel->fd());
+        }
+    };
+    cli.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
+        printf("< %.*s\n", (int)buf->size(), (char*)buf->data());
+    };
+    cli.start();
+
+    while (1) hv_sleep(1);
+    return 0;
+}
+```
+
 ### HTTP
 #### HTTP服务端
 见[examples/http_server_test.cpp](examples/http_server_test.cpp)
 
-**golang gin style**
+**golang gin 风格**
 ```c++
 #include "HttpServer.h"
 
@@ -145,7 +278,7 @@ int main() {
 #### HTTP客户端
 见[examples/http_client_test.cpp](examples/http_client_test.cpp)
 
-**python requests style**
+**python requests 风格**
 ```c++
 #include "requests.h"
 
@@ -168,7 +301,7 @@ int main() {
 }
 ```
 
-**js axios style**
+**js axios 风格**
 ```c++
 #include "axios.h"
 
@@ -214,19 +347,7 @@ int main() {
 }
 ```
 
-#### HTTP压测
-```shell
-# sudo apt install wrk
-wrk -c 100 -t 4 -d 10s http://127.0.0.1:8080/
-
-# sudo apt install apache2-utils
-ab -c 100 -n 100000 http://127.0.0.1:8080/
-```
-
-**libhv(port:8080) vs nginx(port:80)**
-![libhv-vs-nginx.png](html/downloads/libhv-vs-nginx.png)
-
-## 🍭 示例
+## 🍭 更多示例
 
 ### c版本
 - 事件循环: [examples/hloop_test.c](examples/hloop_test.c)
@@ -263,6 +384,8 @@ ab -c 100 -n 100000 http://127.0.0.1:8080/
 - 服务注册与发现: [examples/consul](examples/consul)
 
 ## 🥇 性能测试
+
+### TCP压测
 ```shell
 cd echo-servers
 ./build.sh
@@ -309,6 +432,20 @@ total readcount=1699652 readbytes=1740443648
 throughput = 165 MB/s
 ```
 
+### HTTP压测
+```shell
+# sudo apt install wrk
+wrk -c 100 -t 4 -d 10s http://127.0.0.1:8080/
+
+# sudo apt install apache2-utils
+ab -c 100 -n 100000 http://127.0.0.1:8080/
+```
+
+**libhv(port:8080) vs nginx(port:80)**
+![libhv-vs-nginx.png](html/downloads/libhv-vs-nginx.png)
+
+以上测试结果可以在 [Github Actions](https://github.com/ithewei/libhv/actions/workflows/benchmark.yml) 中查看。
+
 ## 📚 中文资料
 
 - **libhv 教程**: <https://hewei.blog.csdn.net/article/details/113733758>

+ 148 - 13
README.md

@@ -98,6 +98,138 @@ bin/curl -v localhost:8080/test -F 'bool=1 int=123 float=3.14 string=hello'
 bin/curl -v -X DELETE localhost:8080/group/test/user/123
 ```
 
+### TCP
+#### tcp server
+**c version**: [examples/tcp_echo_server.c](examples/tcp_echo_server.c)
+```c
+#include "hloop.h"
+
+static void on_close(hio_t* io) {
+    printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
+}
+
+static void on_recv(hio_t* io, void* buf, int readbytes) {
+    // echo
+    hio_write(io, buf, readbytes);
+}
+
+static void on_accept(hio_t* io) {
+    hio_setcb_close(io, on_close);
+    hio_setcb_read(io, on_recv);
+    hio_read(io);
+}
+
+int main() {
+    int port = 1234;
+    hloop_t* loop = hloop_new(0);
+    hio_t* listenio = hloop_create_tcp_server(loop, "0.0.0.0", port, on_accept);
+    if (listenio == NULL) {
+        return -1;
+    }
+    hloop_run(loop);
+    hloop_free(&loop);
+    return 0;
+}
+```
+
+**c++ version**: [evpp/TcpServer_test.cpp](evpp/TcpServer_test.cpp)
+```c++
+#include "TcpServer.h"
+using namespace hv;
+
+int main() {
+    int port = 1234;
+    TcpServer srv;
+    int listenfd = srv.createsocket(port);
+    if (listenfd < 0) {
+        return -1;
+    }
+    printf("server listen on port %d, listenfd=%d ...\n", port, listenfd);
+    srv.onConnection = [](const SocketChannelPtr& channel) {
+        std::string peeraddr = channel->peeraddr();
+        if (channel->isConnected()) {
+            printf("%s connected! connfd=%d\n", peeraddr.c_str(), channel->fd());
+        } else {
+            printf("%s disconnected! connfd=%d\n", peeraddr.c_str(), channel->fd());
+        }
+    };
+    srv.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
+        // echo
+        channel->write(buf);
+    };
+    srv.setThreadNum(4);
+    srv.start();
+
+    while (1) hv_sleep(1);
+    return 0;
+}
+```
+
+#### tcp client
+**c version**: [examples/nc.c](examples/nc.c)
+```c
+#include "hloop.h"
+
+static void on_close(hio_t* io) {
+    printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
+}
+
+static void on_recv(hio_t* io, void* buf, int readbytes) {
+    printf("< %.*s\n", readbytes, (char*)buf);
+}
+
+static void on_connect(hio_t* io) {
+    hio_setcb_close(io, on_close);
+    hio_setcb_read(io, on_recv);
+    hio_read(io);
+
+    hio_write(io, "hello", 5);
+}
+
+int main() {
+    int port = 1234;
+    hloop_t* loop = hloop_new(0);
+    hio_t* connio = hloop_create_tcp_client(loop, "127.0.0.1", port, on_connect);
+    if (connio == NULL) {
+        return -1;
+    }
+    hloop_run(loop);
+    hloop_free(&loop);
+    return 0;
+}
+```
+
+**c++ version**: [evpp/TcpClient_test.cpp](evpp/TcpClient_test.cpp)
+```c++
+#include "TcpClient.h"
+using namespace hv;
+
+int main() {
+    int port = 1234;
+    TcpClient cli;
+    int connfd = cli.createsocket(port);
+    if (connfd < 0) {
+        return -1;
+    }
+    cli.onConnection = [](const SocketChannelPtr& channel) {
+        std::string peeraddr = channel->peeraddr();
+        if (channel->isConnected()) {
+            printf("connected to %s! connfd=%d\n", peeraddr.c_str(), channel->fd());
+            channel->write("hello");
+        } else {
+            printf("disconnected to %s! connfd=%d\n", peeraddr.c_str(), channel->fd());
+        }
+    };
+    cli.onMessage = [](const SocketChannelPtr& channel, Buffer* buf) {
+        printf("< %.*s\n", (int)buf->size(), (char*)buf->data());
+    };
+    cli.start();
+
+    while (1) hv_sleep(1);
+    return 0;
+}
+```
+
 ### HTTP
 #### http server
 see [examples/http_server_test.cpp](examples/http_server_test.cpp)
@@ -212,19 +344,7 @@ int main() {
 }
 ```
 
-#### http benchmark
-```shell
-# sudo apt install wrk
-wrk -c 100 -t 4 -d 10s http://127.0.0.1:8080/
-
-# sudo apt install apache2-utils
-ab -c 100 -n 100000 http://127.0.0.1:8080/
-```
-
-**libhv(port:8080) vs nginx(port:80)**
-![libhv-vs-nginx.png](html/downloads/libhv-vs-nginx.png)
-
-## 🍭 Examples
+## 🍭 More examples
 ### c version
 - [examples/hloop_test.c](examples/hloop_test.c)
 - [examples/tcp_echo_server.c](examples/tcp_echo_server.c)
@@ -260,6 +380,7 @@ ab -c 100 -n 100000 http://127.0.0.1:8080/
 - [examples/consul](examples/consul)
 
 ## 🥇 Benchmark
+### tcp benchmark
 ```shell
 cd echo-servers
 ./build.sh
@@ -305,3 +426,17 @@ throughput = 132 MB/s
 total readcount=1699652 readbytes=1740443648
 throughput = 165 MB/s
 ```
+
+### http benchmark
+```shell
+# sudo apt install wrk
+wrk -c 100 -t 4 -d 10s http://127.0.0.1:8080/
+
+# sudo apt install apache2-utils
+ab -c 100 -n 100000 http://127.0.0.1:8080/
+```
+
+**libhv(port:8080) vs nginx(port:80)**
+![libhv-vs-nginx.png](html/downloads/libhv-vs-nginx.png)
+
+Above test results can be found on [Github Actions](https://github.com/ithewei/libhv/actions/workflows/benchmark.yml).

+ 17 - 6
docs/API.md

@@ -37,7 +37,6 @@
 - IS_HEX
 - IS_LOWER, IS_UPPER
 - LOWER, UPPER
-- LD, LU, LLD, LLU
 - MAKEWORD, LOBYTE, HIBYTE
 - MAKELONG, LOWORD, HIWORD
 - MAKEINT64, LOINT, HIINT
@@ -289,15 +288,27 @@
 
 ## utils
 ### md5.h
-- MD5Init
-- MD5Update
-- MD5Final
+- 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
-- base64_decode
-- base64_encode
+- hv_base64_decode
+- hv_base64_encode
 
 ### json.hpp
+- json::parse
+- json::dump
 
 ### hmain.h
 - main_ctx_init

+ 4 - 0
docs/PLAN.md

@@ -13,3 +13,7 @@
 
 - mqtt client
 - redis client
+- lua binding
+- js binding
+- hrpc = libhv + protobuf
+- reliable udp: FEC, ARQ, KCP, UDT, QUIC

+ 1 - 3
evpp/EventLoopThreadPool_test.cpp

@@ -1,9 +1,7 @@
 /*
  * EventLoopThreadPool_test.cpp
  *
- * @build
- * make libhv && sudo make install
- * g++ -std=c++11 EventLoopThreadPool_test.cpp -o EventLoopThreadPool_test -I/usr/local/include/hv -lhv -lpthread
+ * @build: make evpp
  *
  */
 

+ 1 - 3
evpp/EventLoopThread_test.cpp

@@ -1,9 +1,7 @@
 /*
  * EventLoopThread_test.cpp
  *
- * @build
- * make libhv && sudo make install
- * g++ -std=c++11 EventLoopThread_test.cpp -o EventLoopThread_test -I/usr/local/include/hv -lhv -lpthread
+ * @build: make evpp
  *
  */
 

+ 1 - 3
evpp/EventLoop_test.cpp

@@ -1,9 +1,7 @@
 /*
  * EventLoop_test.cpp
  *
- * @build
- * make libhv && sudo make install
- * g++ -std=c++11 EventLoop_test.cpp -o EventLoop_test -I/usr/local/include/hv -lhv -lpthread
+ * @build: make evpp
  *
  */
 

+ 1 - 3
evpp/TcpClient_test.cpp

@@ -1,9 +1,7 @@
 /*
  * TcpClient_test.cpp
  *
- * @build
- * make libhv && sudo make install
- * g++ -std=c++11 TcpClient_test.cpp -o TcpClient_test -I/usr/local/include/hv -lhv -lpthread
+ * @build: make evpp
  *
  */
 

+ 1 - 3
evpp/TcpServer_test.cpp

@@ -1,9 +1,7 @@
 /*
  * TcpServer_test.cpp
  *
- * @build
- * make libhv && sudo make install
- * g++ -std=c++11 TcpServer_test.cpp -o TcpServer_test -I/usr/local/include/hv -lhv -lpthread
+ * @build: make evpp
  *
  */
 

+ 1 - 3
evpp/UdpClient_test.cpp

@@ -1,9 +1,7 @@
 /*
  * UdpClient_test.cpp
  *
- * @build
- * make libhv && sudo make install
- * g++ -std=c++11 UdpClient_test.cpp -o UdpClient_test -I/usr/local/include/hv -lhv -lpthread
+ * @build: make evpp
  *
  */
 

+ 1 - 3
evpp/UdpServer_test.cpp

@@ -1,9 +1,7 @@
 /*
  * UdpServer_test.cpp
  *
- * @build
- * make libhv && sudo make install
- * g++ -std=c++11 UdpServer_test.cpp -o UdpServer_test -I/usr/local/include/hv -lhv -lpthread
+ * @build: make evpp
  *
  */
 

+ 10 - 1
examples/tcp_chat_server.c

@@ -13,6 +13,8 @@
 #include "hbase.h"
 #include "list.h"
 
+unpack_setting_t unpack_setting;
+
 // hloop_create_tcp_server
 // on_accept => join
 // on_recv => broadcast
@@ -115,7 +117,8 @@ static void on_accept(hio_t* io) {
 
     hio_setcb_close(io, on_close);
     hio_setcb_read(io, on_recv);
-    hio_read(io);
+    hio_set_unpack(io, &unpack_setting);
+    hio_read_start(io);
 
     // free on_close
     connection_t* conn = NULL;
@@ -133,6 +136,12 @@ int main(int argc, char** argv) {
     }
     int port = atoi(argv[1]);
 
+    memset(&unpack_setting, 0, sizeof(unpack_setting_t));
+    unpack_setting.package_max_length = DEFAULT_PACKAGE_MAX_LENGTH;
+    unpack_setting.mode = UNPACK_BY_DELIMITER;
+    unpack_setting.delimiter[0] = '\n';
+    unpack_setting.delimiter_bytes = 1;
+
     hloop_t* loop = hloop_new(0);
     hio_t* listenio = hloop_create_tcp_server(loop, "0.0.0.0", port, on_accept);
     if (listenio == NULL) {