English | 中文
Like libevent, libev, and libuv
,
libhv
provides event-loop with non-blocking IO and timer,
but simpler api and richer protocols.
- Cross-platform (Linux, Windows, MacOS, Solaris)
- EventLoop (IO, timer, idle)
- TCP/UDP client/server/proxy
- SSL/TLS support: WITH_OPENSSL or WITH_MBEDTLS
- HTTP client/server (include https http1/x http2 grpc)
- HTTP file service, indexof service, api service (support RESTful)
- WebSocket client/server
see BUILD.md
Makefile:
./configure
make
sudo make install
or cmake:
mkdir build
cd build
cmake ..
cmake --build .
or vcpkg:
vcpkg install libhv
or xmake:
xrepo install libhv
run ./getting_started.sh
:
git clone https://github.com/ithewei/libhv.git
cd libhv
make
bin/httpd -h
bin/httpd -d
#bin/httpd -c etc/httpd.conf -s restart -d
ps aux | grep httpd
# http file service
bin/curl -v localhost:8080
# http indexof service
bin/curl -v localhost:8080/downloads/
# http api service
bin/curl -v localhost:8080/ping
bin/curl -v localhost:8080/echo -d "hello,world!"
bin/curl -v localhost:8080/query?page_no=1\&page_size=10
bin/curl -v localhost:8080/kv -H "Content-Type:application/x-www-form-urlencoded" -d 'user=admin&pswd=123456'
bin/curl -v localhost:8080/json -H "Content-Type:application/json" -d '{"user":"admin","pswd":"123456"}'
bin/curl -v localhost:8080/form -F "user=admin pswd=123456"
bin/curl -v localhost:8080/upload -F "file=@LICENSE"
bin/curl -v localhost:8080/test -H "Content-Type:application/x-www-form-urlencoded" -d 'bool=1&int=123&float=3.14&string=hello'
bin/curl -v localhost:8080/test -H "Content-Type:application/json" -d '{"bool":true,"int":123,"float":3.14,"string":"hello"}'
bin/curl -v localhost:8080/test -F 'bool=1 int=123 float=3.14 string=hello'
# RESTful API: /group/:group_name/user/:user_id
bin/curl -v -X DELETE localhost:8080/group/test/user/123
see examples/http_server_test.cpp
golang gin style
#include "HttpServer.h"
int main() {
HttpService router;
router.GET("/ping", [](HttpRequest* req, HttpResponse* resp) {
return resp->String("pong");
});
router.GET("/data", [](HttpRequest* req, HttpResponse* resp) {
static char data[] = "0123456789";
return resp->Data(data, 10);
});
router.GET("/paths", [&router](HttpRequest* req, HttpResponse* resp) {
return resp->Json(router.Paths());
});
router.GET("/get", [](HttpRequest* req, HttpResponse* resp) {
resp->json["origin"] = req->client_addr.ip;
resp->json["url"] = req->url;
resp->json["args"] = req->query_params;
resp->json["headers"] = req->headers;
return 200;
});
router.POST("/echo", [](HttpRequest* req, HttpResponse* resp) {
resp->content_type = req->content_type;
resp->body = req->body;
return 200;
});
http_server_t server;
server.port = 8080;
server.service = &router;
http_server_run(&server);
return 0;
}
see examples/http_client_test.cpp
python requests style
#include "requests.h"
int main() {
auto resp = requests::get("http://www.example.com");
if (resp == NULL) {
printf("request failed!\n");
} else {
printf("%s\n", resp->body.c_str());
}
resp = requests::post("127.0.0.1:8080/echo", "hello,world!");
if (resp == NULL) {
printf("request failed!\n");
} else {
printf("%s\n", resp->body.c_str());
}
return 0;
}
js axios style
#include "axios.h"
int main() {
const char* strReq = R"({
"method": "POST",
"url": "http://127.0.0.1:8080/echo",
"params": {
"page_no": "1",
"page_size": "10"
},
"headers": {
"Content-Type": "application/json"
},
"body": {
"app_id": "123456",
"app_secret": "abcdefg"
}
})";
// sync
auto resp = axios::axios(strReq);
if (resp == NULL) {
printf("request failed!\n");
} else {
printf("%s\n", resp->body.c_str());
}
// async
int finished = 0;
axios::axios(strReq, [&finished](const HttpResponsePtr& resp) {
if (resp == NULL) {
printf("request failed!\n");
} else {
printf("%s\n", resp->body.c_str());
}
finished = 1;
});
// wait async finished
while (!finished) hv_sleep(1);
return 0;
}
# 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)
- examples/hloop_test.c
- examples/tcp_echo_server.c
- examples/tcp_chat_server.c
- examples/tcp_proxy_server.c
- examples/udp_echo_server.c
- examples/udp_proxy_server.c
- evpp/EventLoop_test.cpp
- evpp/EventLoopThread_test.cpp
- evpp/EventLoopThreadPool_test.cpp
- evpp/TcpServer_test.cpp
- evpp/TcpClient_test.cpp
- evpp/UdpServer_test.cpp
- evpp/UdpClient_test.cpp
- examples/http_server_test.cpp
- examples/http_client_test.cpp
- examples/websocket_server_test.cpp
- examples/websocket_client_test.cpp
cd echo-servers
./build.sh
./benchmark.sh
throughput:
libevent running on port 2001
libev running on port 2002
libuv running on port 2003
libhv running on port 2004
asio running on port 2005
poco running on port 2006
==============2001=====================================
[127.0.0.1:2001] 4 threads 1000 connections run 10s
total readcount=1616761 readbytes=1655563264
throughput = 157 MB/s
==============2002=====================================
[127.0.0.1:2002] 4 threads 1000 connections run 10s
total readcount=2153171 readbytes=2204847104
throughput = 210 MB/s
==============2003=====================================
[127.0.0.1:2003] 4 threads 1000 connections run 10s
total readcount=1599727 readbytes=1638120448
throughput = 156 MB/s
==============2004=====================================
[127.0.0.1:2004] 4 threads 1000 connections run 10s
total readcount=2202271 readbytes=2255125504
throughput = 215 MB/s
==============2005=====================================
[127.0.0.1:2005] 4 threads 1000 connections run 10s
total readcount=1354230 readbytes=1386731520
throughput = 132 MB/s
==============2006=====================================
[127.0.0.1:2006] 4 threads 1000 connections run 10s
total readcount=1699652 readbytes=1740443648
throughput = 165 MB/s