|
|
@@ -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)**
|
|
|
-
|
|
|
-
|
|
|
-## 🍭 示例
|
|
|
+## 🍭 更多示例
|
|
|
|
|
|
### 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)**
|
|
|
+
|
|
|
+
|
|
|
+以上测试结果可以在 [Github Actions](https://github.com/ithewei/libhv/actions/workflows/benchmark.yml) 中查看。
|
|
|
+
|
|
|
## 📚 中文资料
|
|
|
|
|
|
- **libhv 教程**: <https://hewei.blog.csdn.net/article/details/113733758>
|