2

私は私を混乱させているエラーがあります。次のコードは、TidTCPClientからTidTCPServerに行を送信します。初めて実行するときは、完全に機能します。2回目の実行時、およびその後の毎回、すべての文字列の先頭に改行が追加されます。私は何が欠けていますか?(私はそれが奇妙な方法でそれを行うことを知っていますが、クライアントのリストは完全なコードで必要です)

   procedure TClientForm.ButtonSendStringClick(Sender: TObject);
    var
      I: integer;
      List: TList;
    begin
      List := ClientList.LockList;
      try
       for I := 0 to (List.Count- 1) do
        begin
          TidTCPClient(List[I]).IOHandler.WriteLn('Hello'+'|x|');
        end;
      finally
       ClientList.UnlockList;
      end;
      Edit1.Text := '';
    end;

    procedure TClientForm.IdTCPServer1Execute(AContext: TIdContext);
    var
    LLine: string;
    begin
    LLine := Acontext.Connection.IOHandler.ReadLn('|x|');
    OutputDebugString(PChar(LLine));
    end;
4

2 に答える 2

3

WriteLn()渡す文字列の最後にCRLFを追加しますが、ReadLn()指定したターミネータ文字列に遭遇すると読み取りを停止します。したがって、送信して'Hello|x|#13#10'いますが、読み取りのみを行っており、次の読み取りを取得するためにソケットバッファに'Hello|x|'残しています。#13#10

問題を解決するには、次の2つの選択肢があります。

1)でカスタムターミネータを引き続き使用する場合はReadLn()、に変更WriteLn()Write()て、暗黙のCRLFが送信されないようにします。ReadLn()通話に変更は必要ありません。

Write('Hello|x|');
LLine := ReadLn('|x|');

2)カスタムターミネータの使用を完全に停止します。メインの文字列だけをに渡してCRLFを追加し、デフォルトのターミネータはLF(CRLFの処理を含む)であるため、WriteLn()ターミネータを渡さないでください。ReadLn()

WriteLn('Hello');
LLine := ReadLn();
于 2012-04-16T15:25:50.847 に答える
2

クライアントコードに潜在的な問題がありますClientList.unlocklist。ループの外で実行する必要があります。

procedure TClientForm.ButtonSendStringClick(Sender: TObject);
var
  I: integer;
  List      : TList; 
begin     
  List := ClientList.LockList;
  try
   for I := 0 to (List.Count- 1) do
    begin
      ShowMessage('Text to encrypt is ' + Edit1.Text);
      TidTCPClient(List[I]).IOHandler.WriteLn((Encrypt(Edit1.Text,'Pass')+'|x|'));      
    end;
  finally
   ClientList.UnlockList;
  end;
  Edit1.Text := '';
end;

サーバーのexecuteイベントでshowmessageを使用しないでください。これは、synchronize別のロギング方法を使用または使用する必要があるメインのGUIスレッドではないためです。他の潜在的な問題は、暗号化された文字列にキャリッジリターン文字またはヌル文字(#0)が含まれている可能性があるという事実です。これらの場合、Readlnサーバーのメソッドは暗号化された文字列全体を読み取ることができず、復号化に失敗します。これを解決する1つの方法は、を使用することbase64 encodingです。

編集

問題は、「|x|」を使用しているという事実にあります。ReadLnと組み合わせたターミネータ。クライアント側からwritelnを使用しているので、これを行うことができます

procedure TClientForm.IdTCPServer1Execute(AContext: TIdContext);
var
 LLine: string;
begin
 LLine := Acontext.Connection.IOHandler.ReadLn;
 OutputDebugString(PChar(LLine));
end;

ターミネータを使用したい場合は使用しないwritelnでくださいreadln

于 2012-04-15T18:05:14.027 に答える