3

我编写了一个简单的 Web 服务器来处理长轮询,这意味着服务器不会向客户端(Web 浏览器、curl 等)发送完整的 HTTP 响应,而只会发送 HTTP 标头并挂起连接。

我使用命令行 curl 向服务器发出请求,它很好地打印出 HTTP 响应标头,并且 curl 按预期挂起。然后我按 CTRL+C 终止 curl 过程。但是服务器永远不会知道这个关闭(永远不会调用on_disconnect())。

一些代码:

void request_handler(struct evhttp_request *req, void *arg){
    // only send response headers, and one piece of chunked data
    evhttp_send_reply_start(req, HTTP_OK, "OK");
    evbuffer_add_printf(buf, "...\n");
    evhttp_send_reply_chunk(req, buf);
    // register connection close callback
    evhttp_connection_set_closecb(req->evcon, on_disconnect, sub);
}

void on_disconnect(struct evhttp_connection *evcon, void *arg){
    printf("disconnected\n");
}

evhttp_set_gencb(http, request_handler, NULL);

我的问题是,如何检测这种客户端关闭(收到 TCP FIN)?

github上的错误

4

1 回答 1

2

我认为这是 libevent 中的一个错误。

我对 libevent 2.0.21 有类似的问题,这就是我的情况:当 libevent 的 http.c 中的 evhttp_read_header() 完成从客户端读取 HTTP 标头时,它会通过调用 bufferevent_disable(.. .,EV_READ)。但是,需要为底层缓冲区事件启用读取事件才能报告 EOF。这就是为什么当客户端关闭连接时,bufferevent 从不告诉 libevent 的 HTTP 代码。

我通过简单地删除 evhttp_read_header() 中对 bufferevent_disable() 的调用解决了这个问题。我使用“连接:关闭”,只使用 GET 请求,因此客户端从不在标头之后发送任何数据,这个解决方案似乎适用于这个非常具体和简单的用例。但是,我不确定这不会破坏其他用例,尤其是当您使用持久连接或“期望:100-继续”之类的东西时。

你可能想把它带到 libevent 邮件列表。

于 2013-09-13T01:16:44.847 回答