- Notifications
You must be signed in to change notification settings - Fork1.3k
🔥 比libevent/libuv/asio更易用的网络库。A c/c++ network library for developing TCP/UDP/SSL/HTTP/WebSocket/MQTT client/server.
License
ithewei/libhv
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
English |中文
Likelibevent, libev, and libuv,libhv provides event-loop with non-blocking IO and timer,but simpler api and richer protocols.
- Cross-platform (Linux, Windows, macOS, Android, iOS, BSD, Solaris)
- High-performance EventLoop (IO, timer, idle, custom, signal)
- TCP/UDP client/server/proxy
- TCP supports heartbeat, reconnect, upstream, MultiThread-safe write and close, etc.
- Built-in common unpacking modes (FixedLength, Delimiter, LengthField)
- RUDP support: WITH_KCP
- SSL/TLS support: (via WITH_OPENSSL or WITH_GNUTLS or WITH_MBEDTLS)
- HTTP client/server (support https http1/x http2 grpc)
- HTTP supports static service, indexof service, forward/reverse proxy service, sync/async API handler
- HTTP supports RESTful, router, middleware, keep-alive, chunked, SSE, etc.
- WebSocket client/server
- MQTT client
seeBUILD.md
Makefile:
./configuremakesudo make install
or cmake:
mkdir buildcd buildcmake ..cmake --build.
or bazel:
bazel build libhv
or vcpkg:
vcpkg install libhv
or xmake:
xrepo install libhv
run./getting_started.sh:
git clone https://github.com/ithewei/libhv.gitcd libhv./configuremakebin/httpd -hbin/httpd -d#bin/httpd -c etc/httpd.conf -s restart -dps aux| grep httpd# http file servicebin/curl -v localhost:8080# http indexof servicebin/curl -v localhost:8080/downloads/# http api servicebin/curl -v localhost:8080/pingbin/curl -v localhost:8080/echo -d"hello,world!"bin/curl -v localhost:8080/query?page_no=1\&page_size=10bin/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' -F'pswd=123456'bin/curl -v localhost:8080/upload -d"@LICENSE"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' -F'int=123' -F'float=3.14' -F'string=hello'# RESTful API: /group/:group_name/user/:user_idbin/curl -v -X DELETE localhost:8080/group/test/user/123# benchmarkbin/wrk -c 1000 -d 10 -t 4 http://127.0.0.1:8080/
c version:examples/tcp_echo_server.c
c++ version:evpp/TcpServer_test.cpp
#include"TcpServer.h"usingnamespacehv;intmain() {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();// press Enter to stopwhile (getchar() !='\n');return0;}
c version:examples/tcp_client_test.c
c++ version:evpp/TcpClient_test.cpp
#include<iostream>#include"TcpClient.h"usingnamespacehv;intmain() {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()); }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(); std::string str;while (std::getline(std::cin, str)) {if (str =="close") { cli.closesocket(); }elseif (str =="start") { cli.start(); }elseif (str =="stop") { cli.stop();break; }else {if (!cli.isConnected())break; cli.send(str); } }return0;}
seeexamples/http_server_test.cpp
golang gin style
#include"HttpServer.h"usingnamespacehv;intmain() { HttpService router; router.GET("/ping", [](HttpRequest* req, HttpResponse* resp) {return resp->String("pong"); }); router.GET("/data", [](HttpRequest* req, HttpResponse* resp) {staticchar 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;return200; }); router.POST("/echo", [](const HttpContextPtr& ctx) {return ctx->send(ctx->body(), ctx->type()); }); HttpServerserver(&router); server.setPort(8080); server.setThreadNum(4); server.run();return0;}
seeexamples/http_client_test.cpp
python requests style
#include"requests.h"intmain() {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()); }return0;}
seeexamples/websocket_server_test.cpp
#include"WebSocketServer.h"usingnamespacehv;intmain(int argc,char** argv) { WebSocketService ws; ws.onopen = [](const WebSocketChannelPtr& channel,const HttpRequestPtr& req) {printf("onopen: GET %s\n", req->Path().c_str()); }; ws.onmessage = [](const WebSocketChannelPtr& channel,const std::string& msg) {printf("onmessage: %.*s\n", (int)msg.size(), msg.data()); }; ws.onclose = [](const WebSocketChannelPtr& channel) {printf("onclose\n"); }; WebSocketServerserver(&ws); server.setPort(9999); server.setThreadNum(4); server.run();return0;}
seeexamples/websocket_client_test.cpp
#include"WebSocketClient.h"usingnamespacehv;intmain(int argc,char** argv) { WebSocketClient ws; ws.onopen = []() {printf("onopen\n"); }; ws.onmessage = [](const std::string& msg) {printf("onmessage: %.*s\n", (int)msg.size(), msg.data()); }; ws.onclose = []() {printf("onclose\n"); };// reconnect: 1,2,4,8,10,10,10...reconn_setting_t reconn;reconn_setting_init(&reconn); reconn.min_delay =1000; reconn.max_delay =10000; reconn.delay_policy =2; ws.setReconnect(&reconn); ws.open("ws://127.0.0.1:9999/test"); std::string str;while (std::getline(std::cin, str)) {if (!ws.isConnected())break;if (str =="quit") { ws.close();break; } ws.send(str); }return0;}
- examples/hloop_test.c
- examples/htimer_test.c
- examples/pipe_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
- examples/socks5_proxy_server.c
- examples/tinyhttpd.c
- examples/tinyproxyd.c
- examples/jsonrpc
- examples/mqtt
- examples/multi-thread/multi-acceptor-processes.c
- examples/multi-thread/multi-acceptor-threads.c
- examples/multi-thread/one-acceptor-multi-workers.c
- evpp/EventLoop_test.cpp
- evpp/EventLoopThread_test.cpp
- evpp/EventLoopThreadPool_test.cpp
- evpp/TimerThread_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
- examples/protorpc
- hv-projects/QtDemo
- examples/nc
- examples/nmap
- examples/httpd
- examples/wrk
- examples/curl
- examples/wget
- examples/consul
- examples/kcptun
cd echo-servers./build.sh./benchmark.shthroughput:
libevent running on port 2001libev running on port 2002libuv running on port 2003libhv running on port 2004asio running on port 2005poco running on port 2006==============2001=====================================[127.0.0.1:2001] 4 threads 1000 connections run 10stotal readcount=1616761 readbytes=1655563264throughput = 157 MB/s==============2002=====================================[127.0.0.1:2002] 4 threads 1000 connections run 10stotal readcount=2153171 readbytes=2204847104throughput = 210 MB/s==============2003=====================================[127.0.0.1:2003] 4 threads 1000 connections run 10stotal readcount=1599727 readbytes=1638120448throughput = 156 MB/s==============2004=====================================[127.0.0.1:2004] 4 threads 1000 connections run 10stotal readcount=2202271 readbytes=2255125504throughput = 215 MB/s==============2005=====================================[127.0.0.1:2005] 4 threads 1000 connections run 10stotal readcount=1354230 readbytes=1386731520throughput = 132 MB/s==============2006=====================================[127.0.0.1:2006] 4 threads 1000 connections run 10stotal readcount=1699652 readbytes=1740443648throughput = 165 MB/s
# sudo apt install iperfiperf -s -p 5001> /dev/null&bin/tcp_proxy_server 1212 127.0.0.1:5001&iperf -c 127.0.0.1 -p 5001 -l 8Kiperf -c 127.0.0.1 -p 1212 -l 8K
Bandwidth:
------------------------------------------------------------[ 3]local 127.0.0.1 port 52560 connected with 127.0.0.1 port 5001[ ID] Interval Transfer Bandwidth[ 3] 0.0-10.0 sec 20.8 GBytes 17.9 Gbits/sec------------------------------------------------------------[ 3]local 127.0.0.1 port 48142 connected with 127.0.0.1 port 1212[ ID] Interval Transfer Bandwidth[ 3] 0.0-10.0 sec 11.9 GBytes 10.2 Gbits/sec
# sudo apt install wrkwrk -c 100 -t 4 -d 10s http://127.0.0.1:8080/# sudo apt install apache2-utilsab -c 100 -n 100000 http://127.0.0.1:8080/
libhv(port:8080) vs nginx(port:80)
Above test results can be found onGithub Actions.
About
🔥 比libevent/libuv/asio更易用的网络库。A c/c++ network library for developing TCP/UDP/SSL/HTTP/WebSocket/MQTT client/server.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.
