NgHttp2 调用请求数据处理程序两次,针对一个请求
Posted
技术标签:
【中文标题】NgHttp2 调用请求数据处理程序两次,针对一个请求【英文标题】:NgHttp2 invokes request data handler twice, for one single request 【发布时间】:2021-10-26 22:20:05 【问题描述】:我正在使用nghttp2
运行 HTTP2 服务器。我试图弄清楚为什么
server.cpp
中的 on_data
处理程序被调用两次。我知道它被调用了两次,因为当我发送请求时
包含数据,我会在服务器中为 single 请求获得以下日志输出。
1
2
但如果我不在请求中发送数据。单个请求的日志输出是我所期望的
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
编译
#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
编译
#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();
【问题讨论】:
【参考方案1】:如果您还打印出数据帧的长度,将会有更多信息需要推理。
我的猜测是客户端为aaaaaaaaaa
和end_stream=false
发送第一个长度为10的DATA
帧,以及第二个长度为0和end_stream=true
的DATA
帧,以表示流的结束在请求方面。
对于不发送内容的情况,客户端可能只发送长度为 0 的 DATA
帧和 end_stream=true
。
我想这可以通过使用不同的 API(sess
上的不同方法或不同的参数)来优化,从而提高效率。
第一种情况,一个有内容的请求,理想情况下有一个长度为 10 的DATA
帧和end_stream=true
,而第二种情况(没有请求内容)只有一个HEADERS
帧和@987654332 @ 并且根本没有 DATA
框架。
【讨论】:
以上是关于NgHttp2 调用请求数据处理程序两次,针对一个请求的主要内容,如果未能解决你的问题,请参考以下文章
使用 boost 数据结构和 nghttp2 的 C++ 程序未编译
使用 mocha 测试 express 服务器并使用异步初始化程序进行 supertest 调用请求两次