You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断HTTP消息是否已完整接收?C语言Web服务器开发疑问

Handling Complete HTTP Message Reception with Chunked Encoding/Binary Attachments (Async Sockets + http-parser)

Great question! Handling asynchronous HTTP parsing with chunked encoding or binary payloads can feel tricky at first, but http-parser is designed specifically to handle this flow—you just need to leverage its event-driven callbacks correctly. Let’s break this down step by step:

1. Let http-parser Do the Heavy Lifting (Don’t Reinvent the Wheel)

http-parser is a streaming parser, which means it doesn’t need the entire HTTP message upfront. It tracks state internally and tells you when key events happen:

  • on_body callback: Triggered every time a chunk of the message body (whether from a Content-Length-defined payload or a single chunk in chunked encoding) is received. This is where you’ll write the data to your buffer or process it incrementally.
  • on_message_complete callback: This is your golden signal! When this fires, the entire HTTP message—all chunks in a chunked request, or all bytes specified by Content-Length, including binary attachments—has been fully received.

For chunked encoding specifically, http-parser automatically handles parsing chunk lengths, processing chunk data, and detecting the final 0\r\n\r\n terminator. You don’t need to manually count bytes or look for chunk boundaries.

2. Async Socket Data Flow: Feed Data Incrementally

Since you’re using async sockets (e.g., with epoll/kqueue), you’ll receive data in arbitrary chunks. Here’s the correct pattern:

  • When your async IO notifier signals a socket has data ready, read it into a buffer (use non-blocking recv to avoid blocking).
  • Call http_parser_execute() with the parser instance, your configured settings (with callbacks), the buffer, and the number of bytes read.
  • If the return value of http_parser_execute() is less than the number of bytes you read, that means some data was left unprocessed (e.g., a chunk’s length was split across two packets). Save this leftover data in a per-connection buffer, and prepend it to the next batch of data you read before feeding it to the parser.

Example snippet to illustrate this:

// Per-connection struct to track leftover data
typedef struct {
    http_parser parser;
    char leftover_buf[BUF_SIZE];
    size_t leftover_len;
    // ... other connection state (e.g., output buffer)
} connection_t;

// When data is available on the socket:
ssize_t bytes_read = recv(conn->fd, temp_buf, BUF_SIZE, MSG_DONTWAIT);
if (bytes_read > 0) {
    char *feed_buf = temp_buf;
    size_t feed_len = bytes_read;

    // If we have leftover data from last time, prepend it
    if (conn->leftover_len > 0) {
        memcpy(conn->leftover_buf + conn->leftover_len, temp_buf, bytes_read);
        feed_buf = conn->leftover_buf;
        feed_len = conn->leftover_len + bytes_read;
        conn->leftover_len = 0;
    }

    // Feed data to the parser
    size_t parsed_bytes = http_parser_execute(&conn->parser, &parser_settings, feed_buf, feed_len);

    // Save any unprocessed data for next time
    if (parsed_bytes < feed_len) {
        memcpy(conn->leftover_buf, feed_buf + parsed_bytes, feed_len - parsed_bytes);
        conn->leftover_len = feed_len - parsed_bytes;
    }
}

3. Binary Attachments? No Special Handling Needed

Binary payloads (like images, files) don’t require any extra work. http-parser only cares about the HTTP protocol framing (Content-Length values or chunk boundaries)—it doesn’t inspect or modify the body content. As long as you collect all data from the on_body callbacks until on_message_complete fires, you’ll have the full binary attachment.

4. Common Pitfalls to Avoid

  • Don’t manually calculate Content-Length or chunk sizes: http-parser already handles edge cases (like chunk extensions, leading/trailing whitespace in headers) that are easy to mess up if you roll your own logic.
  • Always reset the parser after on_message_complete: Once a full message is processed, call http_parser_init() on your parser instance to reset its state for the next incoming request.
  • Don’t discard leftover data: Asynchronous IO guarantees nothing about packet boundaries—saving unprocessed bytes is critical for correct parsing.

Final Takeaway

You don’t need to manually check if the message is complete. Let on_message_complete be your indicator. Your job is to keep feeding incoming data (plus any leftover bytes) to http-parser, and trust that it’ll tell you when the entire request/response is ready.

内容的提问来源于stack exchange,提问作者Kamal Palei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:23:08