关于使用nghttp2库实现Server Sent Events(SSE)的技术问询
nghttp2对Server Sent Events(SSE)的支持与实现思路
nghttp2本身支持基于HTTP/1.x实现SSE,因为SSE本质是HTTP/1.x协议下的长连接分块推送机制,而nghttp2库包含完整的HTTP/1.x服务器/客户端实现(不仅限于HTTP/2)。官方文档未专门提及SSE,是因为SSE并非HTTP/2特性(HTTP/2有原生的Server Push机制),但完全可以基于其HTTP/1.x API实现SSE功能。
实现核心要点
要实现SSE,你需要在服务器端完成以下关键步骤:
设置正确的响应头
必须为响应添加以下HTTP头,确保客户端识别为SSE流:Content-Type: text/event-streamCache-Control: no-cacheConnection: keep-alive
nghttp2会自动处理Transfer-Encoding: chunked(HTTP/1.x分块传输是SSE的基础)。
分块发送SSE格式数据
SSE的事件格式遵循规范,每个事件通常由data:字段开头,以空行结尾。例如:data: 这是一条SSE消息\n\n也可以添加
id:(事件ID)或event:(事件类型)字段来丰富事件信息:id: 123 event: update data: 状态已更新\n\n基于nghttp2的HTTP/1.x API实现推送循环
在请求处理回调中,先提交响应头,然后进入循环,周期性生成SSE格式数据并通过nghttp2的API发送,直到客户端断开连接。
代码示例框架
以下是基于nghttp2 1.56.0-DEV版本的服务器端实现简化示例:
#include <nghttp2/nghttp2.h> #include <stdio.h> #include <unistd.h> #include <string.h> // 请求处理回调 int on_request(nghttp2_http_server *server, nghttp2_http_session *session, const nghttp2_http_req *req, void *user_data) { // 仅处理指定SSE请求路径 if (strcmp(req->path, "/sse") != 0) { nghttp2_http_server_response(session, 404, NULL, 0, NULL, 0); return 0; } // 设置SSE响应头 nghttp2_nv headers[] = { NGHTTP2_NV("Content-Type", "text/event-stream", NGHTTP2_NV_FLAG_NONE), NGHTTP2_NV("Cache-Control", "no-cache", NGHTTP2_NV_FLAG_NONE), NGHTTP2_NV("Connection", "keep-alive", NGHTTP2_NV_FLAG_NONE), }; // 提交200响应头 nghttp2_http_server_response(session, 200, headers, sizeof(headers)/sizeof(nghttp2_nv), NULL, 0); // 周期性推送SSE事件 int count = 0; char buf[256]; while (1) { // 检查客户端连接状态 if (nghttp2_http_session_is_closed(session)) { break; } // 构造SSE事件内容 snprintf(buf, sizeof(buf), "data: 第%d条SSE消息\n\n", ++count); // 提交数据块并发送 nghttp2_data_provider data_prd = {NULL, NULL}; nghttp2_session_submit_data(session, NULL, buf, strlen(buf), 0, &data_prd); nghttp2_session_send(session); // 模拟1秒推送间隔 sleep(1); } return 0; } int main() { nghttp2_http_server server; int rv; // 初始化HTTP服务器(默认兼容HTTP/1.x与HTTP/2) rv = nghttp2_http_server_init(&server, NULL); if (rv != 0) { fprintf(stderr, "服务器初始化失败: %d\n", rv); return 1; } // 绑定请求处理回调 nghttp2_http_server_set_on_request_callback(&server, on_request, NULL); // 监听8080端口 rv = nghttp2_http_server_listen(&server, "0.0.0.0", 8080, 0); if (rv != 0) { fprintf(stderr, 端口监听失败: %d\n", rv); nghttp2_http_server_free(&server); return 1; } // 启动服务器事件循环 nghttp2_http_server_run(&server); nghttp2_http_server_free(&server); return 0; }
注意事项
- 编译时需链接nghttp2库,例如:
gcc sse-server.c -o sse-server -lnghttp2。 - SSE仅适用于HTTP/1.x连接,客户端发起SSE请求时会自动使用HTTP/1.x协议(SSE不兼容HTTP/2)。
- 生产环境中需补充错误处理、超时管理逻辑,避免无效循环占用资源。
内容的提问来源于stack exchange,提问作者Michael Roeper
相关产品推荐
相关产品推荐

