【问题标题】:How to read evbuffer and put it into a string (char*) in libevent如何读取 evbuffer 并将其放入 libevent 中的字符串 (char*)
【发布时间】:2025-12-31 15:20:13
【问题描述】:

我正在使用 libevent 及其 http API 来编写一个能够编写 C servlet 的简单 HTTP 服务器。此 servlet 与 GET 一起工作正常,但现在我正在使用 POST 发送一些数据,我想读取传入的事件缓冲区 evb。我想打印/检查 evb 中存在的数据,但我不能。你知道如何将数据放入 char* 变量中的 evb (evbuffer) 中吗?我只看到了操作缓冲区的方法,但没有看到它。我试过了:

evb->

这是代码:

    #include <stdio.h>
    #include "servlet.h"

    void servlet(struct evhttp_request *req, struct evbuffer *evb) {
        time_t now;
        time(&now);
        evbuffer_add_printf(evb, "<html>\n <head>\n"
            "  <title>%s</title>\n"
            " </head>\n"
            " <body>\n"
            "  <h1>%s</h1>\n"
            " <p>Current time is: %s</p>",
            "C servlet engine", "C servlet", ctime(&now));
        evhttp_add_header(evhttp_request_get_output_headers(req),
            "Content-Type", "text/html");
        evhttp_send_reply(req, 200, "OK", evb);
    }

I am trying this 

void servlet(struct evhttp_request *req, struct evbuffer *evb) {
    size_t len = evbuffer_get_length(evhttp_request_get_input_buffer(req));
    struct evbuffer *in_evb = evhttp_request_get_input_buffer(req);
    char *data;
    evbuffer_copyout(in_evb, data, len);

但我得到总线错误:10(我在 Mac 上)

【问题讨论】:

    标签: c unix libevent


    【解决方案1】:

    听起来你想用

    ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data, size_t datalen)
    

    它将缓冲区内容(最多datalen字节)复制到内存区域data。 它记录在libevent book

    【讨论】:

    • 是的,我正在尝试该功能,但出现 Bus error: 10 see my update。
    • 你需要为数据变量分配内存,例如:data = malloc(len)
    • 我必须初始化数据变量 char *data = malloc(len);
    【解决方案2】:

    这是一个有效的方法:

    static void echo_read_cb(struct bufferevent *bev, void *ctx)
    {
    /* This callback is invoked when there is data to read on bev. */
    struct evbuffer *input = bufferevent_get_input(bev);
    struct evbuffer *output = bufferevent_get_output(bev);
    
    size_t len = evbuffer_get_length(input);
    char *data;
    data = malloc(len);
    evbuffer_copyout(input, data, len);
    
    printf("we got some data: %s\n", data);
    
    /* Copy all the data from the input buffer to the output buffer. */
    evbuffer_add_buffer(output, input);
    free(data);
    }
    

    【讨论】:

      【解决方案3】:

      根据libevent的buffer.h中的源码,我们应该使用

      int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
      

      而不是

      ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen);
      

      这是从buffer.h借来的代码

      /**
        Read data from an evbuffer and drain the bytes read.
      
        If more bytes are requested than are available in the evbuffer, we
        only extract as many bytes as were available.
      
        @param buf the evbuffer to be read from
        @param data the destination buffer to store the result
        @param datlen the maximum size of the destination buffer
        @return the number of bytes read, or -1 if we can't drain the buffer.
       */
      int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
      
      /**
        Read data from an evbuffer, and leave the buffer unchanged.
      
        If more bytes are requested than are available in the evbuffer, we
        only extract as many bytes as were available.
      
        @param buf the evbuffer to be read from
        @param data_out the destination buffer to store the result
        @param datlen the maximum size of the destination buffer
        @return the number of bytes read, or -1 if we can't drain the buffer.
       */
      ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen);
      

      【讨论】: