HTTP/2 是 HTTP 协议的重大升级,提供了更高效的传输性能和更好的用户体验。nghttp2 是一个非常流行的 HTTP/2 实现库,本文将通过解析 nghttp2 的源码以及实现一个简单的客户端示例,帮助读者深入理解 HTTP/2。
HTTP/2 引入了多个新特性来提升性能,包括:
nghttp2 是一个用 C 语言编写的高性能 HTTP/2 库,提供了客户端、服务器和代理的实现。它包括以下几个主要组件:
nghttp2 的源码结构清晰,主要包括以下目录:
我们重点关注 lib/nghttp2 目录下的文件,其中包含了 HTTP/2 协议的核心实现。
在 nghttp2 的初始化过程中,首先会创建会话并设置相关参数。以下是 nghttp2_session_client_new
函数的简化版:
int nghttp2_session_client_new(nghttp2_session **session_ptr,
const nghttp2_session_callbacks *callbacks,
void *user_data) {
return nghttp2_session_new(session_ptr, callbacks, user_data,
NGHTTP2_CLIENT);
}
解释:
该函数创建一个新的 HTTP/2 客户端会话,接受回调函数和用户数据作为参数,并调用 nghttp2_session_new
函数完成实际的初始化工作。
发送请求时,会使用 nghttp2_submit_request
函数,该函数接受会话、优先级、头部和数据回调等参数:
int nghttp2_submit_request(nghttp2_session *session,
const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva, size_t nvlen,
const nghttp2_data_provider *data_prd,
void *stream_user_data) {
// 实现代码
}
解释:
nghttp2_submit_request
函数向服务器发送 HTTP/2 请求。nva
是头部数组,data_prd
是数据提供者,用于提供请求体数据。
处理响应时,会使用 nghttp2_session_mem_recv
函数,该函数从缓冲区中读取数据并解析:
ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
const uint8_t *in, size_t inlen) {
// 实现代码
}
解释:
nghttp2_session_mem_recv
函数从输入缓冲区 in
中读取数据,并将其交给 nghttp2 会话进行处理。
下面是一个简单的 HTTP/2 客户端示例,使用 nghttp2 库发送请求并处理响应。
示例代码:
#include
#include
#include
#include
// 回调函数,用于处理响应数据
static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
fwrite(data, 1, len, stdout);
return 0;
}
int main(int argc, char **argv) {
nghttp2_session_callbacks *callbacks;
nghttp2_session *session;
nghttp2_nv nva[] = {
MAKE_NV(":method", "GET"),
MAKE_NV(":path", "/"),
MAKE_NV(":scheme", "https"),
MAKE_NV(":authority", "example.com")
};
// 初始化回调函数
nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
// 创建会话
nghttp2_session_client_new(&session, callbacks, NULL);
// 发送请求
nghttp2_submit_request(session, NULL, nva, sizeof(nva) / sizeof(nva[0]),
NULL, NULL);
// 处理响应
uint8_t buffer[4096];
ssize_t read_len = read(STDIN_FILENO, buffer, sizeof(buffer));
nghttp2_session_mem_recv(session, buffer, read_len);
// 清理资源
nghttp2_session_del(session);
nghttp2_session_callbacks_del(callbacks);
return 0;
}
解释:
on_data_chunk_recv_callback
用于处理接收到的响应数据。nghttp2_session_client_new
创建一个新的客户端会话。nghttp2_submit_request
发送 GET 请求。nghttp2_session_mem_recv
处理。