如何防止KeepAlive=true时TIdHTTPServer发送多余HTML内容?
问题:KeepAlive=true时Indy HTTP服务器发送多余HTML内容
环境与场景
- 使用C++Builder XE6 + Indy 10.6.0.5122搭建REST服务器,核心组件为
TIdHTTPServer和TIdServerIOHandlerSSLOpenSSL - 客户端定时发起请求:每5000毫秒发送一次GET请求,每60000毫秒发送一次POST请求
- 服务器响应规则:收到GET请求返回
200 OK及JSON内容;收到POST请求返回204 No Content无内容响应
异常现象
- 当
KeepAlive = false时,HTTP和HTTPS通信均正常 - 当
KeepAlive = true时,客户端会每隔与POST请求间隔一致的时间(约60000毫秒)收到服务器发送的多余HTML内容:
Recv 15-06-2026 15:40:02.851: <HTML><BODY><B>204 No Content</B></BODY></HTML><EOL>
- 若将POST请求间隔改为10000毫秒,客户端也会每隔约10000毫秒收到该HTML内容,内容为上次POST响应的残留
- 该HTML内容偶尔会紧跟POST请求到达,导致客户端触发
EIdHTTPProtocolException异常,日志如下:
Error 15-06-2026 16:11:52.643: PostEquipment(): EIdHTTPProtocolException: POST /equipment <HTML><BODY><B>204 No Content</B></BODY></HTML>
服务器OnCommandGet事件处理代码
void __fastcall TMainForm::HTTPCommandGet (TIdContext *AContext, TIdHTTPRequestInfo *ARequestInfo, TIdHTTPResponseInfo *AResponseInfo) { TCommandHandler Handler; // Initialize. Handler.Context = AContext; Handler.RequestInfo = ARequestInfo; Handler.ResponseInfo = AResponseInfo; Handler.ListHistory = ListHistory; Handler.EditVehiclesURI = EditVehiclesURI; Handler.ListVehiclesResponse = ListVehiclesResponse; Handler.ListVehiclesAction = ListVehiclesAction; Handler.ListVehiclesCondition = ListVehiclesCondition; Handler.BtnVehiclesLimitsAsText = BtnVehiclesLimitsAsText; Handler.ListVehicles = ListVehicles; Handler.EditEquipmentURI = EditEquipmentURI; Handler.ListEquipmentResponse = ListEquipmentResponse; Handler.TreeEquipment = TreeEquipment; Handler.ListEquipment = ListEquipment; Handler.EditStatusURI = EditStatusURI; Handler.ListStatusResponse = ListStatusResponse; Handler.ListStatus = ListStatus; Handler.EditResultsURI = EditResultsURI; Handler.ListResultsResponse = ListResultsResponse; Handler.ListResults = ListResults; // Add request to 'History' list-view. TThread::Synchronize(NULL, &Handler.LogRequest); // Process request. TThread::Synchronize(NULL, &Handler.ProcessRequest); // Check if request should be ignored. if (AResponseInfo->ResponseNo <= 0) { // Prevent sending response. AResponseInfo->HeaderHasBeenWritten = true; return; } // Generate headers. if (!AResponseInfo->HeaderHasBeenWritten) AResponseInfo->WriteHeader(); // If only headers requested, clear content. if (ARequestInfo->CommandType == hcHEAD) AResponseInfo->ContentText = _D(""); // Send response. String S = AResponseInfo->ContentText; // NOTE: WriteContent() clears ContentText and ContentStream properties. AResponseInfo->WriteContent(); AResponseInfo->ContentText = S; // Add response to 'History' list-view. TThread::Synchronize(NULL, &Handler.LogResponse); // Clear content. AResponseInfo->ContentText = _D(""); }
更新内容
客户端异常日志代码
try { HTTP->PostJSON(Config.BaseURL + Config.ResourceEquipment, Devices.ToJSON()); } catch (Exception &E) { AddLog(logError, _D("PostEquipment(): ") + E.ClassName() + _D(": ") + HTTP->Request->Method + _D(" ") + HTTP->Request->URL + _D("\r\n") + E.Message); }
Wireshark捕获结果
No. Time Source Destination Protocol Length Info 68 31.044634600 192.168.1.49 192.168.1.72 TCP 271 1274 → 80 [PSH, ACK] Seq=3057 Ack=1712 Win=65400 Len=217 [TCP PDU reassembled in 70] 69 31.086929000 192.168.1.72 192.168.1.49 TCP 54 80 → 1274 [ACK] Seq=1712 Ack=3274 Win=65318 Len=0 70 31.087180000 192.168.1.49 192.168.1.72 HTTP/JSON 292 POST /equipment HTTP/1.1 , JSON (application/json) 71 31.101679800 192.168.1.72 192.168.1.49 HTTP 161 HTTP/1.1 204 No Content 72 31.294104800 192.168.1.49 192.168.1.72 TCP 60 1274 → 80 [ACK] Seq=3512 Ack=1819 Win=65293 Len=0 73 31.294141700 192.168.1.72 192.168.1.49 HTTP 103 Continuation 74 31.513229700 192.168.1.49 192.168.1.72 TCP 60 1274 → 80 [ACK] Seq=3512 Ack=1868 Win=65244 Len=0
- 第73行的TCP Continuation包含客户端收到的多余HTML内容,Wireshark将其识别为独立的异常HTTP响应
提问
如何防止服务器在KeepAlive = true时发送这些多余的HTML内容?
内容的提问来源于stack exchange,提问作者Martin Nijhoff
相关产品推荐
相关产品推荐

