【问题标题】:Why does TTcpClient drop data on SendStream()?为什么 TTcpClient 在 SendStream() 上丢弃数据?
【发布时间】:2015-05-22 17:20:25
【问题描述】:

当我调用 TTcpClient.SendStream(MyStream) 时,它会将 MyStream.Position 推进到 8704,我必须反复调用 SendStream() 才能让它完全发送我的流。但是,接收到的数据大约每 8K 丢失 512 个字节的块。

注意:这个问题是修辞性的,因为我曾尝试在网络上找到解决方案但未能成功。我在 Delphi 7 Sockets.pas 中发现了该错误,并希望发布解决方案以造福社区。

【问题讨论】:

  • 认真的吗?对此投反对票?为什么?

标签: sockets delphi stream delphi-7 tcpclient


【解决方案1】:

问题是 Delphi 7 Sockets.pas 中的一个编码错误。该错误会导致任何大于约 8K(确切大小取决于操作系统)的流丢失 512 字节的数据块。 SendStream 实现使用 repeat..until 循环从调用者的流中提取 512 字节的缓冲区以使用 SendBuf() 发送,只要流有数据并且 SendBuf() 不返回等于 SOCKET_ERROR,它就会继续。当 Windows 套接字缓冲区填满时会发生丢失,导致 SendBuf() 返回等于 SOCKET_ERROR,但此时已从调用者的流中读取了多达 512 个字节,并且流位置已提前 - 但该位置未恢复退出时。原始 Sockets.pas 代码:

函数 TBaseSocket.SendStream(AStream: TStream): 整数; 变量 BufLen:整数; 缓冲区:字节数组[0..511]; 开始 结果:= 0; 如果已分配(AStream)然后开始 重复 BufLen := AStream.Read(Buffer, SizeOf(Buffer)); 直到 (BufLen = 0) 或 (SendBuf(Buffer, BufLen) = SOCKET_ERROR); 结尾; 结尾;

这是一个修复:

函数 TBaseSocket.SendStream(AStream: TStream): 整数; 变量 退出:布尔值; BufLen,OldPosition:整数; 缓冲区:字节数组[0..511]; 开始 结果:= 0; 如果已分配(AStream)然后开始 重复 OldPosition := AStream.Position; BufLen := AStream.Read(Buffer, SizeOf(Buffer)); 如果 (BufLen > 0) 然后开始 退出 := (SendBuf(Buffer, BufLen) = SOCKET_ERROR); 如果退出则 AStream.Position := OldPosition; //恢复! end else begin //BufLen = 0 退出:=真; 结尾; 直到退出; 结尾; 结尾;

【讨论】:

  • 认真的吗?对此投反对票?!我很想知道为什么。
猜你喜欢
  • 1970-01-01
  • 2010-10-21
  • 1970-01-01
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多