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;

2番目の(実際にはもっと重要な)質問:

現在、アクセス違反 (アドレス 000000 からの読み取り) が時々発生しています。明らかに行で:

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

ただし、AContext / Connection / InputBuffer / IOHandler = nil BEFORE が false かどうかを確認します。呼び出しの後 (および例外が発生した後)、IOHandler は nil です。

RAD Studio / Delphi 2007 を使用しています。

4

3 に答える 3

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

さて、私が持っている最も単純な onExecute ハンドラーはこのようなものです。(Delphi の代わりに C++ で申し訳ありませんが、そのアイデアは理解できるでしょう。

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

説明したように IOHandler が nil になる唯一の方法は、アプリ内の別のスレッドが、ワーカー スレッドがまだ実行されている間に接続で Disconnect() を呼び出した場合です。

于 2009-06-19T19:16:23.983 に答える