【发布时间】:2020-06-10 11:38:12
【问题描述】:
“读取超时”异常在 ReadBytes(B1, 600, False) 引发 50% 的连接请求和 20% 在 ReadBytes(B3, 5, False)。所以只有少数连接正确完成。 我知道在客户端制作 600 个字节的过程不会超过 2 秒。顺便说一句,如果我将 ReadTimeout 从 10000 增加到 20000,结果并没有改善。 大约有 50 个客户端通常在不同的时间连接,所以我们没有拥挤的服务器。 我设置 ReadTimeout 的目标是在出现问题时尽快关闭连接。 我的代码有什么问题,还是应该在其他地方搜索问题?
procedure TForm1.IdTCPServerExecute(AContext: TIdContext);
var
Log: TConnectionLog;
B1, B2, B3: TIdBytes;
begin
try
try
Log := TConnectionLog.Create;
Log.ConnectDateTime := Now;
Log.ClientIP := AContext.Binding.PeerIP;
AContext.Connection.IOHandler.ReadTimeout := 10000;
AContext.Connection.IOHandler.ReadBytes(B1, 600, False);
AContext.Connection.IOHandler.ReadTimeout := IdTimeoutDefault;
Log.Bytes600ReceiveDateTime := Now;
SetLength(B2, 200);
AContext.Connection.IOHandler.Write(B2);
Log.Bytes200SendDateTime := Now;
AContext.Connection.IOHandler.ReadTimeout := 15000;
AContext.Connection.IOHandler.ReadBytes(B3, 5, False);
AContext.Connection.IOHandler.ReadTimeout := IdTimeoutDefault;
Log.Bytes5ReceiveDateTime := Now;
except
on E: Exception do
begin
Log.ExceptionMessage := E.Message;
raise;
end;
end;
finally
TThread.Synchronize(nil,
procedure
begin
SaveLog(Log);
end);
Log.Free;
end;
end;
德尔福 10.2; 印地10.6.2; 网络类型:2G/GPRS
【问题讨论】:
-
ReadTimeout被应用为每字节超时,因此如果您真的遇到超时,那么您的读取与客户端的发送不匹配,或者您的流量根本没有按预期到达。使用嗅探器仔细检查任一方式 -
@RemyLebeau 感谢您的评论,我会尝试的。代码的另一个小问题:当客户端正常断开连接时,避免“连接正常关闭”异常的正确方法是什么?
-
异常并不总是错误;这是一个基本的。您不应将其视为错误。在那之后,我唯一可以添加的只是“文档”和“查找它”。这是一个反复出现的问题(我记得@RemyLebeau 对代码所做的关于这个问题的反复出现的评论)。检查ww2.indyproject.org/KB/index.html?whydoikeepgettingeidconnc.htm 和stackoverflow.com/questions/1085933/…
-
@Thorba:可以在 TIdTCPServer.OnException 事件处理程序中引发“正常关闭连接”而不会产生任何问题,但问题是它“有时”在我的 try/except 块中引发。正如“文档”所说:“......您的客户端已尝试读取或写入连接。”。但我在服务器端,读取连接时我不期望它。我可以在代码中忽略它,没问题,但不一致的行为对我来说是可疑的,因为“有时”在 try/except 块中会引发异常。
-
@hsn
EIdConnClosedGracefully是服务器端的正常行为,您不应该避免它。如果你抓住它,就不要记录它,但不要丢弃它。让它逃逸OnExecute以便TIdTCPServer可以处理它以正确清理调用线程(否则,您必须手动关闭连接)。您正在做正确的事情来重新raise捕获的异常,这是首选操作。