Like libevent and libuv, libhv provides event-loop with non-blocking IO and timer, but simpler api and richer protocols.

Build Status Platform

中文版

Intro

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, Mac, Solaris)
  • event-loop (IO, timer, idle)
  • ENABLE_IPV6
  • ENABLE_UDS (Unix Domain Socket)
  • WITH_OPENSSL or WITH_MBEDTLS
  • http client/server (include https http1/x http2 grpc)
  • http web service, indexof service, api service (support RESTful API)
  • protocols
    • dns
    • ftp
    • smtp
  • apps
    • ifconfig
    • ping
    • nc
    • nmap
    • nslookup
    • ftp
    • sendmail
    • httpd
    • curl

Getting Started

./getting_started.sh

HTTP

http server

see examples/http_server_test.cpp

#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.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;
}

http client

see examples/http_client_test.cpp

#include "requests.h"

int main() {
    auto resp = requests::get("http://www.example.com");
    if (resp == NULL) {
        printf("request failed!\n");
    } else {
        printf("%d %s\r\n", resp->status_code, resp->status_message());
        printf("%s\n", resp->body.c_str());
    }

    auto resp = requests::post("127.0.0.1:8080/echo", "hello,world!");
    if (resp == NULL) {
        printf("request failed!\n");
    } else {
        printf("%d %s\r\n", resp->status_code, resp->status_message());
        printf("%s\n", resp->body.c_str());
    }

    return 0;
}

httpd/curl

git clone https://github.com/ithewei/libhv.git
cd libhv
make httpd curl

bin/httpd -h
bin/httpd -d
#bin/httpd -c etc/httpd.conf -s restart -d
ps aux | grep httpd

# http web 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 "[email protected]"

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

benchmark

# webbench (linux only)
make webbench
bin/webbench -c 2 -t 10 http://127.0.0.1:8080/
bin/webbench -k -c 2 -t 10 http://127.0.0.1:8080/

# sudo apt install apache2-utils
ab -c 100 -n 100000 http://127.0.0.1:8080/

# sudo apt install wrk
wrk -c 100 -t 4 -d 10s http://127.0.0.1:8080/

libhv(port:8080) vs nginx(port:80) libhv-vs-nginx.png

EventLoop

see examples/tcp_echo_server.c examples/udp_echo_server.c examples/nc.c

// TCP echo server
#include "hloop.h"

void on_close(hio_t* io) {
}

void on_recv(hio_t* io, void* buf, int readbytes) {
    hio_write(io, buf, readbytes);
}

void on_accept(hio_t* io) {
    hio_setcb_close(io, on_close);
    hio_setcb_read(io, on_recv);
    hio_read(io);
}

int main(int argc, char** argv) {
    if (argc < 2) {
        printf("Usage: cmd port\n");
        return -10;
    }
    int port = atoi(argv[1]);

    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 -20;
    }
    hloop_run(loop);
    hloop_free(&loop);
    return 0;
}
make examples

bin/tcp_echo_server 1234
bin/nc 127.0.0.1 1234

bin/tcp_chat_server 1234
bin/nc 127.0.0.1 1234
bin/nc 127.0.0.1 1234

bin/httpd -s restart -d
bin/tcp_proxy_server 1234 127.0.0.1:8080
bin/curl -v 127.0.0.1:8080
bin/curl -v 127.0.0.1:1234

bin/udp_echo_server 1234
bin/nc -u 127.0.0.1 1234

BUILD

see BUILD.md

lib

  • make libhv
  • sudo make install

examples

  • make examples

unittest

  • make unittest

compile options

compile WITH_OPENSSL

Enable SSL in libhv is so easy, just only two apis:

// init ssl_ctx, see base/hssl.h
hssl_ctx_t hssl_ctx_init(hssl_ctx_init_param_t* param);

// enable ssl, see event/hloop.h
int hio_enable_ssl(hio_t* io);

https is the best example.

sudo apt install openssl libssl-dev # ubuntu
make clean
make WITH_OPENSSL=yes
# editor etc/httpd.conf => ssl = on
bin/httpd -s restart -d
bin/curl -v https://localhost:8080
curl -v https://localhost:8080 --insecure

compile WITH_CURL

make WITH_CURL=yes DEFINES="CURL_STATICLIB"

compile WITH_NGHTTP2

sudo apt install libnghttp2-dev # ubuntu
make clean
make WITH_NGHTTP2=yes
bin/httpd -d
bin/curl -v localhost:8080 --http2

other options

see config.mk

echo-servers

cd echo-servers
./build.sh
./benchmark.sh

echo-servers/benchmark
echo-servers

Owner
Comments
  • The websockets use NULL to make ctx to retry connection in the pause stage make it unsafe.

    The websockets use NULL to make ctx to retry connection in the pause stage make it unsafe.

    You can see if you give the bad crt or key or ca file. at first, it check the server and refuses the connect. However, when it is in the HLOOP_STATUS_PAUSE stage, it will try to use the null to make ctx to connect. It can connect to the unsafe server. why it have the three process? what is the three ssl come from? image image image

    image

  • [Question] http response prase header missing the default domain,path?

    [Question] http response prase header missing the default domain,path?

    For example,the server set a cookie but without domain and path,like:

    cookie=cookie123
    

    And the response will give us:

    cookie=cookie123
    

    The header doesn't contain the domain and path without setting them,it is a normal response as usual as we did.

    But in many development scenarios,we need to getting the default domain and path.

    I 've checked the source code in "Http1Parser.cpp":

    //line 26
    if (stricmp(header_field.c_str(), "Set-CooKie") == 0 ||
        stricmp(header_field.c_str(), "Cookie") == 0) {
        HttpCookie cookie;
        if (cookie.parse(header_value)) {
            parsed->cookies.emplace_back(cookie);
        }
    }
    

    It told me that libhv just parse Cookie's domain and path from response header.

    I think it isn't enough,I suggest that we need to save the domain and path form request,if the response header haven't contained them,we can use the saved values.

    Looking forward to your reply,thank you.

  • websocket server halt

    websocket server halt

    我集成了libhv的websocket server到自己的应用里,对比windows版本的hv.dll和linux版本的libhv.so测试同样的场景,浏览器发起连接和断开连接在win10和centos7下websocket server都正常, 但当浏览器没有正常断开websocket连接,而直接跳转到其他页面的情况下,windows的websocket server工作正常,再重新用浏览器连接成功。centos7下的websocket server无法再用浏览器连接,只有重启应用服务才行。

  • Help, I'm new!

    Help, I'm new!

    Hi, I'm new to GitHub and I want to start helping out in some project. Could someone be kind enough to just let me know how the code is compiled into one URL and how are they connected here in Github. I understand how the pull requests, branches, issues section, and a little bit of markdown work ( because I took the intro course from the lab ), but I don't get how all this code thrown in the code tab compiles/connects as one and contributes to building the software. Final question: is github only for building websites? Or how and where is the software built here used and applied elsewhere. If this is not a project/server that encourages new guys then I deeply apologise and appreciate your time. also, what is the main purpose of this project? Thanks

  • Couldn't connect to wss on android

    Couldn't connect to wss on android

    Hi, there is a test websockets site socketsbay.com where can test websocket client, on ios it works well, but on android i always receive this error W/JNI: connfd=146 connect error: Unknown error 1041:1041 also i cant do any https requests, again on ios everything works fine.

  • How to compile for android on mac?

    How to compile for android on mac?

    He, maybe you can help me? i have receive this error: /bin/sh: arm-linux-gnueabi-gcc: command not found

    make[1]: [Makefile.in:275: clean] Error 1 (ignored)
    #-rm -r 2>/dev/null lib
    #-rm -r 2>/dev/null bin
    make[1]: Leaving directory '/Users/sergeigolishnikov/develpment/libhv'
    rm -r 2>/dev/null examples/*.o examples/*/*.o
    make: [Makefile:72: clean] Error 1 (ignored)
    rm -r 2>/dev/null include/hv
    make: [Makefile:73: clean] Error 1 (ignored)
    
  • use CMake method to compile libhv has problem to link the library? use the configure mothed have problem with the .h file?

    use CMake method to compile libhv has problem to link the library? use the configure mothed have problem with the .h file?

    image You can find the websocket_client_test use the system lib /usr/local/lib/libhv.so rather than the llib in the source code.

    Anther probem in the configure mothed, when you use make to compile it. you can find the change in the .h file is recovered. I think it is still because the header file in the system direction.

  • update base/hlog.h base/hlog.c  support char*

    update base/hlog.h base/hlog.c support char*

    • 修改了base/hlog.h中奇怪的宏,参数之间没有逗号,感觉很奇怪; 当前代码如果fmt为char*类型会报错 image

    • 测试代码:

    #include <string>
    #include "hloop.h"
    #include "hbase.h"
    #include "hlog.h"
    #include "nlog.h"
    
    void mylogger(int loglevel, const char* buf, int len) {
        if (loglevel >= LOG_LEVEL_ERROR) {
            stderr_logger(loglevel, buf, len);
        }
    
        if (loglevel >= LOG_LEVEL_INFO) {
            file_logger(loglevel, buf, len);
        }
    }
    
    int main(int argc, char* argv[]) {
        logger_set_handler(hlog, mylogger);
    
        std::string str = "my data: %d";
    
        hloge(str.c_str(), 111);
        hloge("msg ...");
        hloge("msg with a number: %d", 222);
        hloge("msg with number and str: : %d ", 333, "test str datat");
    
        return 0;
    }
    
    
    • 修改前,运行以上测试代码有如下报错: Snipaste_2021-12-18_23-46-36

    • 修改后,代码正常编译通过,运行后输出如下,hloge能支持char*为首个参数: Snipaste_2021-12-18_23-38-39

  • About Connection Pool of AsyncHttpClient

    About Connection Pool of AsyncHttpClient

    我在进行AsyncHttpClient进行压力测试过程中发现一个现象。 我自始至终只申请了一个AsyncHttpClient实例。通过该实例对一个地址进行压力测试。大概是每秒中发起8000个请求。持续10分钟。在此期间,发现其对同一个地址,一共建立了200个http长连接。

    我看了代码,似乎只有对不同的地址才会发起不同的连接。 请问AsyncHttpClient的连接池是如何管理这些连接的。

  • Crash by memory error when getting POST multipart form data param

    Crash by memory error when getting POST multipart form data param

    I have tried to get form data param from request on postman or other c++ codes

    static int preprocessor(HttpRequest* req, HttpResponse* resp) { req->ParseBody();

    return 0; }

    router.preprocessor = preprocessor; router.POST("/uploadReport", [&router](HttpRequest* req, HttpResponse* resp) { std::string fileName = req->GetString("report_name") + ".png"; return req->SaveFormFile("report", fileName.c_str()); });

    but server is crashed by memory error in line which gets fileName Would you help me? Best Regards

  • How can a TcpClient disconnect from a TcpServer manually?

    How can a TcpClient disconnect from a TcpServer manually?

    Hi, I've create a TcpClient instance with hv::TcpClient. By default, it can connect to a desired server by createsocket, but I want to connect or disconnect manually. How can I achieve this while keep the created socket open (without using close function)?

  • 异步响应中调用异步http请求,centos下无法响应

    异步响应中调用异步http请求,centos下无法响应

    代码如下

    std::shared_ptr<std::string> RequestPbf(const std::string& url, const std::string& path, const std::string& body, HttpContextPtr ctx)
    {
    	HttpRequestPtr req(new HttpRequest);
    	req->method = HTTP_POST;
    	req->url = url + path;
    	req->headers["Connection"] = "keep-alive";
    	req->body = body;
    	req->timeout = 10;
    	http_client_send_async(req, [ctx](const HttpResponsePtr& resp) {
    		printf("test_http_async_client response thread tid=%ld\n", hv_gettid());
    		if (resp == NULL) {
    			//...
    			return;
    		}
    		else {
    			printf("%d %s\r\n", resp->status_code, resp->status_message());
    			printf("%s\n", resp->body.c_str());
    		}
    		ctx->send(resp->body, APPLICATION_OCTET_STREAM);   //<<------------------
    		});
    }
    
    router.GET("/test", [](const HttpContextPtr& ctx) {
        PLOG_DEBUG("----");
    	hv::async([ctx]() {
    		//...
    		RequestPbf(ctx);
    		});
    	return 0;
    	});
    

    在windows下,能接收客户端请求,并正常返回,centos下,多进程方式,无法接收请求,PLOG_DEBUG("----");都没有输出,不知道是什么原因?是否还是和线程池有关?

  • multicast support

    multicast support

    请添加组播功能支持

    please add support to multicast utility func like this

    bool is_multicast_addr(const char* addr)
    {   
        //ipv4 only
        addr = ntohl(inet_addr(addr));
        return (addr >> 28) == 0xE;
    }
    
    // IP_MULTICAST_IF
    HV_INLINE int set_ip_multicast_if(SOCKET sock, const char* ifaddr)
    {
        struct in_addr addr;
        addr.s_addr = inet_addr(ifaddr);
        return setsockopt(sock, IPPROTO_IP,IP_MULTICAST_IF,(void *)&addr,sizeof(addr));
    }
    
    // IP_ADD_MEMBERSHIP
    HV_INLINE int join_group(SOCKET sock, const char* gaddr, const char* ifaddr)
    {
        struct ip_mreq mreq= {0};
        mreq.imr_multiaddr.s_addr = inet_addr(gaddr);
        mreq.imr_interface.s_addr = inet_addr(ifaddr);
        return setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq));
    }
    

    also IP_DROP_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP, IP_MULTICAST_TTL, IP_MULTICAST_LOOP

  • remove assert in hio_set_unpack

    remove assert in hio_set_unpack

    协议报文本身多变,body长度的字段 可能在 body_offset之后。所以这里的assert是不正常的提示。 例如,报文是 [0xff, 0xff, 0x3, 0x2(长度字段), 0xA], 前两个字节是head,0x3是类型,0x2是body_len(0x3和0x2两个字节),0xA是校验位 设置时候,body_offset= 2,length_field_offset= 3,length_field_bytes=1, length_adjustment= 1。 这里与assert相悖,所以应该去除assert语句。

Full-featured high-performance event loop loosely modelled after libevent

libev is a high-performance event loop/event model with lots of features. (see benchmark at http://libev.schmorp.de/bench.html) ABOUT Homepage:

Sep 30, 2022
Header-only, event based, tiny and easy to use libuv wrapper in modern C++ - now available as also shared/static library!

Do you have a question that doesn't require you to open an issue? Join the gitter channel. If you use uvw and you want to say thanks or support the pr

Sep 28, 2022
Event loop friendly C++ actor micro-framework

Rotor rotor is event loop friendly C++ actor micro framework, github gitee features minimalistic loop agnostic core erlang-like hierarchical superviso

Sep 4, 2022
KBMS is a C++11 high performance network framework based on libevent.

KBMS is a C++11 high performance network framework based on libevent. It is light and easy to deploy. At present, it mainly supports HTTP protocol.

Sep 13, 2022
Native C++ coroutines for libevent

libevent-async libevent-async is a C++ wrapper around the libevent API. It wraps commonly-used objects in classes and provides coroutine support for m

Jan 8, 2022
The Telegram Bot API provides an HTTP API for creating Telegram Bots.

The Telegram Bot API provides an HTTP API for creating Telegram Bots.

Sep 26, 2022
Encapsulates the two protocols of OpenVpn and Ikev2, you only need to enter the server IP and port number to realize the connection and status display, and the specific situation of the connection can be displayed at the same time。

NewVpnCore 封装了OpenVpn和Ikev2两种协议,只需要输入服务器IP和端口号即可实现连接和状态显示,同时可以显示连接的具体情况。 UniteVpn Core(第一版) 1. 模块说明 unitevpn:封装了vpn的操作和统一不同协议信息的模块 ikev2:IKEV2协议的源码 op

Jun 8, 2022
Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution
Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution

CppServer Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and

Sep 28, 2022
We use Clash as the backend proxy, which supports Shadowsocks(R), V2Ray, and Trojan protocols.
We use Clash as the backend proxy, which supports Shadowsocks(R), V2Ray, and Trojan protocols.

We use Clash as the backend proxy, which supports Shadowsocks(R), V2Ray, and Trojan protocols.

Sep 24, 2022
A modern C++ network library for developing high performance network services in TCP/UDP/HTTP protocols.
A modern C++ network library for developing high performance network services in TCP/UDP/HTTP protocols.

evpp Introduction 中文说明 evpp is a modern C++ network library for developing high performance network services using TCP/UDP/HTTP protocols. evpp provid

Sep 29, 2022
RPC based on C++ Workflow. Supports Baidu bRPC, Tencent tRPC, thrift protocols.
RPC based on C++ Workflow. Supports Baidu bRPC, Tencent tRPC, thrift protocols.

中文版入口 SRPC Introduction SRPC is an RPC system developed by Sogou. Its main features include: Base on Sogou C++ Workflow, with the following features:

Sep 23, 2022
Event-driven network library for multi-threaded Linux server in C++11

Muduo is a multithreaded C++ network library based on the reactor pattern. http://github.com/chenshuo/muduo Copyright (c) 2010, Shuo Chen. All righ

Sep 26, 2022
About Add any Program in any language you like or add a hello world Program ❣️ if you like give us ⭐

Hello-World About Add any Program in any language you like or add a hello world Program ❣️ if you like give us ⭐ Give this Project a Star ⭐ If you lik

Aug 23, 2022
A special version of Packet Batch that utilizes AF_XDP Linux sockets (this should be faster than the standard version, but not as fast as the DPDK).

Packet Batch (AF_XDP) Description This is a special version of Packet Batch that utilizes AF_XDP sockets instead of AF_PACKETv3 (which is what the sta

Sep 14, 2022
A simple networking library for C++. Designed with games in mind, but can be used for other things

A simple networking library for C++. Designed with games in mind, but can be used for other things. Tested to work on Android and Windows.

Nov 14, 2019
Webdav-client-cpp - C++ WebDAV Client provides easy and convenient to work with WebDAV-servers.

WebDAV Client Package WebDAV Client provides easy and convenient to work with WebDAV-servers: Yandex.Disk Dropbox Google Drive Box 4shared ownCloud ..

Oct 1, 2022
Level up your Beat Saber experience on Quest! AnyTweaks provides various tweaks to help boost your experience on Quest, such as Bloom, FPS Counter and more.

Need help/support? Ask in one of BSMG's support channels for Quest, or join my Discord server! AnyTweaks Level up your Beat Saber experience on Quest!

Aug 29, 2022
GNOME Shell provides core user interface functions for the GNOME 3 desktop

GNOME Shell GNOME Shell provides core user interface functions for the GNOME 3 desktop, like switching to windows and launching applications. GNOME Sh

Oct 18, 2021