我编写了一个处理长轮询的简单Web服务器,这意味着服务器不会向客户端发送完整的HTTP响应(Web浏览器,curl等),但只发送HTTP头并挂起连接
我使用命令行curl向服务器发出请求,它会很好地打印出HTTP响应标头,并且curl会按预期挂起。然后我按CTRL + C来终止卷曲过程。但服务器永远不会知道这个接近(永远不会调用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)?
的错误答案 0 :(得分:2)
我认为这是libevent中的一个错误。
我对libevent 2.0.21有类似的问题,这就是我的情况:当libevent的http.c中的evhttp_read_header()完成从客户端读取HTTP头时,它通过调用bufferevent_disable来禁用任何将来的读事件(...,EV_READ)。但是,需要为底层bufferevent启用读取事件以报告EOF。这就是为什么当客户端关闭连接时,bufferevent永远不会告诉libevent的HTTP代码。
我通过在evhttp_read_header()中删除对bufferevent_disable()的调用来解决我的问题。我使用“连接:关闭”,只有GET请求,所以客户端永远不会在标题之后发送任何数据,这个解决方案似乎适用于这个非常具体和简单的用例。但是,我不确定这是否会破坏其他用例,尤其是当您使用持久连接或“Expect:100-continue”之类的事情时。
你可能想把它带到libevent邮件列表。