Libhv
🔥 比libevent/libuv/asio更易用的网络库。A c/c++ network library for developing TCP/UDP/SSL/HTTP/WebSocket/MQTT client/server.
Install / Use
/learn @ithewei/LibhvREADME
English | 中文
libhv
Like libevent, libev, and libuv,
libhv provides event-loop with non-blocking IO and timer,
but simpler api and richer protocols.
✨ Features
- 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
⌛️ Build
see BUILD.md
Makefile:
./configure
make
sudo make install
or cmake:
mkdir build
cd build
cmake ..
cmake --build .
or bazel:
bazel build libhv
or vcpkg:
vcpkg install libhv
or xmake:
xrepo install libhv
⚡️ Getting Started
run ./getting_started.sh:
git clone https://github.com/ithewei/libhv.git
cd libhv
./configure
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' -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_id
bin/curl -v -X DELETE localhost:8080/group/test/user/123
# benchmark
bin/wrk -c 1000 -d 10 -t 4 http://127.0.0.1:8080/
TCP
tcp server
c version: examples/tcp_echo_server.c
c++ version: evpp/TcpServer_test.cpp
#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();
// press Enter to stop
while (getchar() != '\n');
return 0;
}
tcp client
c version: examples/tcp_client_test.c
c++ version: evpp/TcpClient_test.cpp
#include <iostream>
#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());
} 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();
} else if (str == "start") {
cli.start();
} else if (str == "stop") {
cli.stop();
break;
} else {
if (!cli.isConnected()) break;
cli.send(str);
}
}
return 0;
}
HTTP
http server
see examples/http_server_test.cpp
golang gin style
#include "HttpServer.h"
using namespace hv;
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", [](const HttpContextPtr& ctx) {
return ctx->send(ctx->body(), ctx->type());
});
HttpServer server(&router);
server.setPort(8080);
server.setThreadNum(4);
server.run();
return 0;
}
http client
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;
}
WebSocket
WebSocket server
see examples/websocket_server_test.cpp
#include "WebSocketServer.h"
using namespace hv;
int main(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");
};
WebSocketServer server(&ws);
server.setPort(9999);
server.setThreadNum(4);
server.run();
return 0;
}
WebSocket client
see examples/websocket_client_test.cpp
#include "WebSocketClient.h"
using namespace hv;
int main(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_polic
Related Skills
canvas
326.5kCanvas Skill Display HTML content on connected OpenClaw nodes (Mac app, iOS, Android). Overview The canvas tool lets you present web content on any connected node's canvas view. Great for: -
node-connect
326.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
80.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
326.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
