libhv is a free, open source databases project written in C and released under BSD-3-Clause. It has 7,551 GitHub stars, 1,365 forks and 41 open issues, and was last pushed 15 hours ago. On this registry it ranks #98 of 143 tracked projects in Databases, with 5 head-to-head comparisons available.

What is libhv?

libhv is a cross-platform C/C++ network library for building TCP, UDP, SSL/TLS, HTTP, WebSocket, MQTT, and Redis clients and servers, written for developers who want the non-blocking event-loop model of libevent, libev, or libuv with a simpler API and more protocols built in.

What it is

libhv supplies an event loop with non-blocking IO and timers, the same foundation that libevent, libev, and libuv provide, but it ships a far wider protocol surface in the same package. It is written in C with a C++-usable interface and runs on Linux, Windows, macOS, Android, iOS, BSD, and Solaris, and its topic list points at epoll and IOCP as the platform readiness mechanisms it builds on. Licence is BSD-3-Clause. In this registry it is filed under Infrastructure & Operations / Databases, although its own scope is networking rather than storage; the Redis topic refers to the bundled client, not to a database engine.

The concrete problem is that a bare event loop stops at sockets and timers. Anyone who needs HTTP, WebSocket, MQTT, or Redis on top of one has to pull in additional libraries, each with its own threading rules, buffering, and TLS setup. libhv replaces that stack: HTTP, WebSocket, MQTT, and Redis clients are built in, TLS arrives through WITH_OPENSSL, WITH_GNUTLS, or WITH_MBEDTLS, and RUDP arrives through WITH_KCP, so a single dependency covers the transport and the protocols above it.

Key capabilities

  • High-performance EventLoop handling IO, timer, idle, custom, and signal events.
  • TCP/UDP client, server, and proxy, with TCP support for heartbeat, reconnect, upstream, and MultiThread-safe write and close.
  • Built-in common unpacking modes: FixedLength, Delimiter, and LengthField.
  • SSL/TLS support chosen at build time via WITH_OPENSSL, WITH_GNUTLS, or WITH_MBEDTLS, and RUDP support via WITH_KCP.
  • HTTP client and server supporting https, http1/x, http2, and grpc, with static service, indexof service, forward/reverse proxy service, and sync/async API handlers.
  • HTTP protocol features including RESTful, router, middleware, keep-alive, chunked, and SSE.
  • WebSocket client/server, plus an MQTT client and a Redis client.

Who uses it and how

  • C and C++ teams building network daemons that need HTTP, WebSocket, and MQTT from one dependency instead of three separate libraries.
  • Service authors writing TCP or UDP proxies and servers that need heartbeat, reconnect, or thread-safe write without hand-rolling those rules.
  • Cross-platform products targeting Android, iOS, BSD, or Solaris alongside Linux and Windows from the same codebase.
  • Evaluators running the bundled bin/httpd example as a file service, indexof service, and API service before integrating the library into their own build.
  • Projects needing RUDP/KCP transport for latency-sensitive traffic, enabled through the WITH_KCP build option.

Getting started

Build from source with ./configure && make && sudo make install, use cmake or bazel with bazel build libhv, or install the packaged artifact with vcpkg install libhv or xrepo install libhv. The README points to ./getting_started.sh and to binaries such as bin/httpd and bin/curl for a first run.

How it compares

The README positions libhv directly against libevent, libev, libuv, and asio: the same event-loop foundation with non-blocking IO and timers, but a simpler API and richer protocols. libevent, libev, libuv, and asio are named as the closest peers that a user would otherwise reach for, and the stated difference is that libhv includes the protocols rather than leaving them to be added separately. No paid products are listed as being replaced by this project.

When to use it — and when not to

A self-hoster has to compile the library and make build-time choices: TLS is inactive until WITH_OPENSSL, WITH_GNUTLS, or WITH_MBEDTLS is selected, and RUDP requires WITH_KCP, so the feature set depends on how the build is configured. No hosted or managed option appears in the facts, and the README is largely a feature list whose build details live in a separate BUILD.md and a wiki homepage, so the documentation is distributed rather than central. Teams that want only a bare event loop, or that need bindings outside C and C++, should look at the libraries named above instead.

project readme (upstream, from github) — read inline

English | 中文

libhv

Linux Windows macOS Android iOS benchmark
release stars forks issues PRs contributors license
gitee awesome-c awesome-cpp

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
  • Redis 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());
    };

readme truncated — read the full docs on github

Frequently asked questions

Is libhv free to use?

libhv is open source under the BSD-3-Clause licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does libhv do?

🔥 比libevent/libuv/asio更易用的网络库。A c/c++ network library for developing TCP/UDP/SSL/HTTP/WebSocket/MQTT/Redis client/server.

What is libhv written in?

libhv is primarily written in C. Its source is publicly available at https://github.com/ithewei/libhv, and it has 7,551 GitHub stars.