【问题标题】:Delphi — TClientSocket ReceiveText MaxLen?Delphi — TClientSocket ReceiveText MaxLen?
【发布时间】:2012-02-08 06:19:57
【问题描述】:

我一直在尝试设置从ReceiveText TClientSocket 函数恢复的字符数量的长度,但似乎没有任何效果。例如,从恢复的数据或其他数据流中接收最左边的第一个字符。有没有办法在 Delphi 中使用这个 specific 对象来完成这个?

我们将不胜感激。提前致谢。

【问题讨论】:

  • PS-也许这个伪代码会给某人一个关于我具体想要实现的假设的见解:hClientSocket.Socket.ReceiveText(1);
  • 欢迎来到 StackOverflow。该站点的工作方式与新闻组略有不同。您可以编辑问题,因此您可以将您的 PS 添加到问题中,而不是使其成为评论。
  • 您使用的是哪个 Delphi 版本?默认情况下,较新的 Delphi 版本不安装 TClientSocket。
  • @JensMühlenhoff:我的意思不是直截了当或无关紧要,但谁说我的 Delphi 发行版中默认安装了 TClientSocket?虽然奇怪的是你猜对了;我没有使用真正最新版本的 Delphi — 准确地说,我使用的是 Delphi 7。但是,为了记录,虽然 TClientSocket 组件可能没有默认安装,但它们是包含在 Delphi 2009+ 中已安装文件的某处,并且可以相应地手动安装。请参阅here 了解更多信息。
  • @MarjanVenema:感谢您的欢迎。是的,我已经习惯了 StackOverflow 系统的工作方式。我将该消息作为评论包含在内,因此它将被视为旁注,而不是与我手头的问题直接相关的内容,因此它不可能掩盖实际问题。

标签: delphi sockets tclientsocket


【解决方案1】:

ReceiveText 无法控制接收文本的最大长度。

ClientType := ctBlocking 模式下最简单的方法是使用 TWinSocketStream,如文档所述:

http://docwiki.embarcadero.com/VCL/XE2/en/ScktComp.TClientSocket.ClientType

当 ClientType 为 ctBlocking 时,使用 TWinSocketStream 对象进行读写。如果在读取或写入时出现问题,TWinSocketStream 可防止应用程序无限期挂起。它还可以等待套接字连接表明它已准备好读取。

示例代码:

var
  Stream : TWinSocketStream;
  Buffer : TBytes;
  S      : string;
begin
  SetLength(Buffer, 100); // 100 bytes buffer size
  Stream := TWinSocketStream.Create(Socket, 5000); // 5 seconds or 5000 milliseconds
  try
    Stream.ReadBuffer(Buffer[0], Length(Buffer)); // raises an Exception if it couldn't read the number of bytes requested
    S := TEncoding.Default.GetString(Buffer); // Works in Delphi 2009+
  finally
    Stream.Free;
  end;
end;

【讨论】:

  • +1 - 我个人认为这是最好的答案。直截了当,直接说明我要完成的工作。然而,TEncoding.Default.GetString 引起了我的注意。我没有使用 Delphi 2009+,所以如果有替代方案,那么在(Borland)Delphi 7.x 之类的版本中实现是什么? 编辑: 哦,凭据不足。不幸的是,不能投票给你。但我冒昧将此标记为我接受的答案。
  • 从头开始;我已经搞定了。再次感谢指点。
  • 我现在已经支持你的问题,这应该会给你在 SO 上的声誉一个开始,顺便说一句:欢迎来到 SO :)
【解决方案2】:

这里有一个发送和接收文本的小技巧

首先你也必须发送你的文本长度

Socket.SendText(IntToStr(Length(text)) + seperator + text);

然后你可以检查你的服务器套接字接收数据流,如果你的传入文本是完整的

procedure TMyServer.OnClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
  if (xRecLength = 0) then begin
    if Length(Socket.ReceiveText) <= 0 then EXIT;
    xRecLength:= StrToIntDef(GetFirstFromSplitted(Socket.ReceiveText, seperator), -1);
    if xRecLength = -1 then EXIT;
  end;
  xActLength:= xActLength + Length(Socket.ReceiveText);
  xRecPuffer:= xRecPuffer + Socket.ReceiveText;

  isComplete:= xActLength = xRecLength;
  if isComplete then begin
    // complete text received
  end;
end;

希望对你有所帮助...

【讨论】:

  • 大部分(如果不是全部)代码与我在这里尝试做的事情无关。虽然我可能弄错了,但乍一看我对此表示怀疑。为了澄清,我基本上是在尝试指定从服务器接收到的字符数量(如果可行的话,最好通过 ReceiveText)。有关示例,请参阅我之前的评论。
  • @user1174509 您可以使用要发送的文本中的前 4 个字节作为数据长度的持有者,或者在字符之前的所有内容,比如美元符号 ($) 以字节为单位指定数据长度,因此,对于 AnsiString,典型的消息看起来像“14$hello 陌生人”,对于 WideString,典型的消息看起来像“28$...”,但我建议搬到 Indy,这样会更好。
  • 我一直在考虑迁移到 Indy 的 TCP 客户端已经有一段时间了。我同时选择坚持使用 TClientSocket 的主要原因之一基本上是简单。另外关于您的评论,您能详细说明一下吗?我对您的大部分意思有深刻的理解,但是澄清一下会很好。
  • 编辑:如果我错了,请纠正我,但是在更彻底地检查了您的帖子之后,问题是这将如何准确地应用于 recovering 数据,而不是当基于你说的是发送它是我想到的。进一步阐述将不胜感激。
【解决方案3】:

我不熟悉 Delphi,但通过 Google 快速搜索出现了 this page,这表明 ReceiveText 不接受任何参数,而是返回一个它可以读取的字符串。

您可能需要的是ReceiveBuf

【讨论】:

  • 感谢您的回答。是的,我知道ReceiveText 不接受参数。这是一个示例,旨在表示我要完成的工作(ReceiveText 方法逐个字符地返回数据)。另外,我曾经尝试过ReceiveBuf,但没有成功。介意提供一个如何通过该路线完成上述任务的示例吗?
  • 此外,在查看您引用的文档后,ReceiveBuf 的潜在问题可能与我使用阻塞套接字而不是非阻塞套接字这一事实有关。在这一点上,利用TWinSocketStream 对象似乎是唯一可行的方法。但是,通过使用标准库 socket 以 Python 之类的语言完成相同的任务,您只需将数据传递给 recv 函数参数(即 socket.recv(BUFFER_SIZE))即可实现。
  • @user1174509 我建议您将该评论作为您自己问题的答案。 :)
  • 是的,我知道这可能是我的问题的解决方案,但是到目前为止,我尝试实施我理论化的方法的尝试都失败了。因此,因此,我正在寻找可能通过代码分发证明的问题的更具体答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-27
  • 2016-04-06
  • 2014-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多