首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NgHttp2为单个请求调用两次请求数据处理程序。

NgHttp2为单个请求调用两次请求数据处理程序。
EN

Stack Overflow用户
提问于 2021-08-26 21:35:27
回答 2查看 189关注 0票数 0

我正在使用HTTP2运行nghttp2服务器。我正在试图弄清楚为什么on_data处理程序在server.cpp中被调用了两次。我知道它被调用了两次,因为当我发送包含数据的请求时,我会得到服务器中的单个请求的以下日志输出。

代码语言:javascript
复制
1
2

但如果我没有在请求中发送数据。单个请求的日志输出是我所期望的。

代码语言:javascript
复制
1

我使用客户端和这一行代码将数据发送到服务器。

auto req = sess.submit(ec, "GET", "http://127.0.0.1:3000/", "aaaaaaaaaa");

为了不发送数据,我只需删除第三个参数。

server.cpp

g++ server.cpp -o server.out -lnghttp2_asio -lboost_system -lcrypto -lpthread -lssl -lboost_thread编译

代码语言:javascript
复制
#include <iostream>
#include <nghttp2/asio_http2_server.h>

using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;

int main() {
    std::string hostname = "127.0.0.1";
    std::string port = "3000";
    boost::system::error_code ec;
    http2 server;

    int count = 0;
    server.handle("/", [&count](const request &req, const response &res) {
        req.on_data([&res, &count](const uint8_t *data, std::size_t len) {
            std::cerr << ++count << '\n';
            res.write_head(200);
            res.end("done");
        });
    });

    if (server.listen_and_serve(ec, hostname, port)) {
        std::cerr << "error: " << ec.message() << std::endl;
    }
}

g++ client.cpp -o client.out -lnghttp2_asio -lboost_system -lcrypto -lpthread -lssl -lboost_thread编译

代码语言:javascript
复制
#include <iostream>

#include <nghttp2/asio_http2_client.h>

using boost::asio::ip::tcp;

using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::client;

int main(int argc, char *argv[]) {
    boost::system::error_code ec;
    boost::asio::io_service io_service;

    // connect to localhost:3000
    session sess(io_service, "127.0.0.1", "3000");

    sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
        boost::system::error_code ec;

        auto req = sess.submit(ec, "GET", "http://127.0.0.1:3000/", "aaaaaaaaaa");
        req->on_response([](const response &res) {
            // print status code and response header fields.
            std::cerr << "HTTP/2 " << res.status_code() << std::endl;
            for (auto &kv : res.header()) {
                std::cerr << kv.first << ": " << kv.second.value << "\n";
            }
            std::cerr << std::endl;

            res.on_data([](const uint8_t *data, std::size_t len) {
                std::cerr.write(reinterpret_cast<const char *>(data), len);
                std::cerr << std::endl;
            });
        });
        req->on_close([&sess](uint32_t error_code) {
            // shutdown session after first request was done.
            sess.shutdown();
        });
    });

    sess.on_error([](const boost::system::error_code &ec) {
        std::cerr << "error: " << ec.message() << std::endl;
    });

    io_service.run();
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-08-26 22:05:43

如果还打印出数据帧的长度,就会有更多的信息需要解释。

我的猜测是,客户端为aaaaaaaaaaend_stream=false发送长度为10的第一个DATA帧,发送长度为0和end_stream=true的第二个DATA帧,以在请求端发送流的结束信号。

对于不发送内容的情况,客户端可能只发送长度为0的DATA帧和end_stream=true

我认为可以通过使用不同的API ( sess上的不同方法或不同的参数)来优化它,以便使其更有效。

第一种情况是包含内容的请求,理想情况下只有长度为10和end_stream=true的单个end_stream=true帧,而第二种情况(没有请求内容)则只有一个带有end_stream=trueHEADERS帧,而根本没有DATA帧。

票数 0
EN

Stack Overflow用户

发布于 2022-07-10 02:57:38

当接收到请求体时,on_data原语被称为N次,直到在nghttp2反应器上接收到的所有数据都被消耗掉。

看看这个要旨

如您所见,当长度为正时,我将使用算法std::复制和字符串流来附加收到的数据块。例如,如果发送806字节,on_data可以用len=806调用一次,或者用len=8调用两次,然后调用len=798。

最后,用on_data调用len=0,然后您可以对整个事务进行流程

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68945568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档