0

第一个问题:

以下例程是 Indy 9 IdTcpServer.OnExecute 例程的正确实现吗?

procedure TMyConnServer.ServerExecute(AContext: TIdPeerThread);
var
  buffSize: integer;
  str:      string;
begin
  AContext.Connection.ReadFromStack(True, 600, False);
  buffSize := AContext.Connection.InputBuffer.Size;
  if (buffSize > 0) then
    { Extract input buffer as string }
    str := AContext.Connection.ReadString(buffSize);

    { Notify connection object of received data }
    if (AContext.Data <> nil) then
    begin
      TConnectionHandler(AContext.Data).Read(str);
    end;
  end;
end;

第二个(实际上更重要的)问题:

现在偶尔会出现访问冲突(从地址 000000 读取)。显然在这条线上:

  AContext.Connection.ReadFromStack(True, 600, False);

但检查 AContext / Connection / InputBuffer / IOHandler = nil BEFORE 是否为假。调用之后(以及引发异常之后),IOHandler 为 nil。

我们正在使用 RAD Studio / Delphi 2007。

4

3 回答 3

0

好吧,我拥有的最简单的 onExecute 处理程序就是这样。(请原谅 C++ 而不是 Delphi,但你会明白的。

void __fastcall MyPanel::DoTCPExecute(TIdPeerThread * AThread)
{
  AnsiString text =AThread->Connection->ReadLn();
  // now do something with text
}

我能看到的唯一明显的问题是你试图使用数据的“时间”来确定你什么时候有一个完整的字符串。这对 TCP 来说是一个真正的禁忌。您可能只有字符串的第一个字节,或者您可能同时发送了多个字符串。使用 TCP 并不能保证每个“发送”最终在另一端作为单个“接收”。

您需要以其他方式“分隔”您的字符串。Readln 使用换行符作为终止符——另一种方法是为每个数据块添加一个长度字段的前缀。您读取长度,然后读取剩余数据。

于 2009-06-19T12:25:29.940 回答
0

代码就是这样工作的,但我认为这不是一个干净的选择:

  if (AContext.Connection.Connected) then
  begin
    try
      AContext.Connection.ReadFromStack(false, 1, false);
    except on E: EAccessViolation do
      // ignore
    end;
  end; 
  buffSize := AContext.Connection.InputBuffer.Size;
于 2009-06-19T13:08:39.290 回答
0

IOHandler 可以像您描述的那样变为 nil 的唯一方法是,如果您的应用程序中的另一个线程在您的工作线程仍在运行时在连接上调用 Disconnect()。

于 2009-06-19T19:16:23.983 回答