我使用TIdTCPClient发送消息并收到答复。我的消息和答案结构相当好,这意味着它们可以有不同的长度,但总是以#FS字符结尾。
我的Delphi (Alexandria)代码如下所示:
_TcpClient := TIdTCPClient.Create(Self);
_TcpClient.ReadTimeout := 60000;
_TcpClient.ConnectTimeout := 30000;
_TcpClient.Host := X.X.X.X;
_TcpClient.Port := Y;然后我发出我的信息:
_TcpClient.Connect;
_TcpClient.IOHandler.Write(messageText);最后,我等待另一方用ACK确认消息(正如我所说,以#FS结束):
try
ans := TStringStream.Create;
repeat
b := _TcpClient.IOHandler.ReadByte;
ans.Write(b,1);
until b = #FS;
b := _TcpClient.IOHandler.ReadByte;
ans.Write(b, 1);
except
_status := ssAckTimeout;
end;所有这些都能很好地应用于短消息,但对于互联网上较大的短信(大约100 K),这一切都失败了。
最后一段代码在8-10秒后落入except部分,没有读取任何内容。
我对组件工作方式的理解是,它应该逐字节读取,等待ReadTimeout或#FS。我不知道为什么它会忽略我的ReadTimeout值,只需8秒就会失败。
有没有人知道答案,或者能提出解决方案?
发布于 2022-10-17 20:38:55
IOHandler.ReadByte()方法确实尊重ReadTimeout属性,尽管您声称它没有。唯一可能比预期早引发错误的方法是,如果操作系统的套接字堆栈中存在缺陷。
但是,您的代码中存在一个潜在的缺陷。循环读取直到#FS到达并写入ans,然后再尝试读取超过#FS的一个字节。除非您的消息实际上有这样一个跟踪字节(可能是校验和?),否则这将失败并破坏您的通信。
在任何情况下,与循环中调用ReadByte()不同,一个更简单的解决方案是使用IOHandler.ReadLn()方法,指定#FS作为分隔符来结束行,例如:
var
ans: string;
...
ans := _TcpClient.IOHandler.ReadLn(#FS);https://stackoverflow.com/questions/74102289
复制相似问题