zeromq / cppzmq

Header-only C++ binding for libzmq
http://www.zeromq.org
MIT License
1.93k stars 757 forks source link

Implementing a simple web server with cppzmq? #546

Closed wbehrens-on-gh closed 2 years ago

wbehrens-on-gh commented 2 years ago

I'm using cppzmq to try and write an embedded web server currently trying to translate this bsd socket tutorial https://dev-notes.eu/2018/06/http-server-in-c/

My code currently looks like this:

#define ADDR std::string("tcp://*:8000")

/**
 * Builds an http header and appends content
 * @param content An html string
 * @return The built header + appended content string
 */
std::string buildHTMLResponse(std::string content) {
    std::string response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n";
    response.append("Content-Length: " + std::to_string(content.length()) + "\r\n\r\n" + content);
    return response;
}

int main() {
    spdlog::set_level(spdlog::level::debug);
    spdlog::info("Starting RCBot");

    zmq::context_t ctx(1);
    zmq::socket_t srv(ctx, zmq::socket_type::stream);

    spdlog::info("Binding socket to: " + ADDR);
    srv.bind(ADDR);

    while(srv.handle() != nullptr) {
        zmq::message_t request;
        std::optional<size_t> bytes = srv.recv(request, zmq::recv_flags::none);
        if(!bytes.has_value()) continue;

        // The http start sequence is 5 bytes
        if(bytes.value() > 0) {
            spdlog::info("Bytes received: " + std::to_string(bytes.value()));
            spdlog::info("Received request: ");
            spdlog::info(request.to_string());

            std::string content = buildHTMLResponse("<h1>Hello!</h1>");
            spdlog::info("Sending response: ");
            spdlog::info(content);
            srv.send(zmq::buffer(content), zmq::send_flags::none);
        }
    }

    spdlog::info("Ending program");
    return 0;
}

I noticed I'm missing some things like listen and accept(unless cppzmq handles that) but currently trying to view the server at localhost:8000 doesnt work and it just loads forever

gummif commented 2 years ago

I think zmq is not a goodfit for this because it is impossible/hard? to determine what connection each message belongs to. Also you should parse the input messages to determine when the request is complete as it might possibly be sent as multiple messages from zmq.

wbehrens-on-gh commented 2 years ago

ah, that's tough. is there another lightweight socket abstraction library you'd recommend?

gummif commented 2 years ago

Well, boost::beast is very good for http and also boost::asio for generic sockets.

wbehrens-on-gh commented 2 years ago

I'm trying to use something more lightweight then boost

gummif commented 2 years ago

Ok, there is also standalone ASIO (not sure about Beast).