0

私は Delphi を初めて使用し、vb.net アプリを変換して学習しようとしています。私が抱えている問題は、TCP/IP ホストからの読み取りです。現在、telnet経由でデバイスに接続してコマンドを送信すると、デバイスはすべてのデータが送信されるまでノンストップでデータを送信します。これは、単に 2 文字の後に CR/LF が続く場合もあれば、可変長データの複数の行である場合もあります。各行の終わりは CR/LF です。コードを書く前に、ハイパーターミナル経由でデバイスに telnet できました。コマンドを送信し、キャプチャ テキストを有効にしてテキスト ファイルに保存します。

以下は私がこれまでに持っているコードです。テキストファイルに保存するためのコーディングはしていません(一度に1ステップずつ)。データはパイプ区切りです。コマンドの送信とデータの受信以外に、デバイスのフォーマットや操作を制御することはできません。ほとんどの場合は機能しますが、すべてのデータ (テスト用に 65 レコード) が受信されない場合があります。私は指導に大いに感謝し、良いか悪いかを問わず、私のコードについて自由にコメントしてください。

function Parse(Char, S: string; Count: Integer): string;
var
  I: Integer;
  T: string;
begin
  if S[Length(S)] <> Char then
    S := S + Char;
  for I := 1 to Count do
  begin
    T := Copy(S, 0, Pos(Char, S) - 1);
    S := Copy(S, Pos(Char, S) + 1, Length(S));
  end;
  Result := T;
end;

procedure TForm2.btnEXITClick(Sender: TObject);
begin
if idTcpClient1.connected then
begin
  idTcpClient1.IOHandler.InputBuffer.clear;
  idTcpClient1.Disconnect;
end;
  Close;
end;

procedure TForm2.btnSendDataClick(Sender: TObject);

var
  mTXDataString : String;
  RXString : String;

begin
  IdTCPClient1.Host := IPAddress.Text;
  IdTCPClient1.Port := StrToInt(IPPort.Text);

  mTXDataString := mTXData.Text + #13#10;

    IdTCPClient1.Connect;

    If IdTCPClient1.Connected then
    begin

      IdTCPClient1.IOHandler.Write(mTXDataString);

      mTXDataString := mTXData.Lines.Text;

      if MTXDataString.Contains('SCHEMA') then
      begin
        mRXData.Lines.Add(IdTCPClient1.IOHandler.ReadLn);
        while not (IdTCPClient1.IOHandler.InputBufferIsEmpty) do
        begin
          RXString := IdTCPClient1.IOHandler.ReadLn;
          If (RXString <> '') and (RXString <> '??') then
          begin
            //Add received data to RXmemo
            mRXData.Lines.Add(RXString);
            //Determine number of records to received based on schema data
            lblRecords.Caption := Parse(',', RXString, 2);

          end;
        end;  //while not
      end     // if

      else
      if mTXDataString.Contains('DATA') then
      begin
        mRXData.Lines.Add(IdTCPClient1.IOHandler.ReadLn);
        while not (IdTCPClient1.IOHandler.InputBufferIsEmpty) do
        begin
          RXString := IdTCPClient1.IOHandler.ReadLn;
          If (RXString <> '') and (RXString <> '??') then
          begin
            mRXData.Lines.Add(RXString);
          end;  // if
        end;    //while not

      end;  // if Schema or not

    end; // if Connected

    IdTCPClient1.Disconnect;

    end; //Procedure
4

1 に答える 1

0

ハイパーターミナルと Telnet アプリは、受信したデータをリアルタイムで表示します。 TIdTCPClientはリアルタイム コンポーネントではありません。いつ、どのように読むかを制御します。データが非同期に到着することを期待している場合、特に受信する行数がわからない場合は、タイマーまたはワーカー スレッドで読み取りを実行する必要があります。次に例を示します。

procedure TForm2.TimerElapsed(Sender: TObject);
var
  S: String;
begin
  if IdTCPClient1.IOHandler = nil then Exit;
  if IdTCPClient1.IOHandler.InputBufferIsEmpty then
  begin
    IdTCPClient1.IOHandler.CheckForDataOnSource(50);
    if IdTCPClient1.IOHandler.InputBufferIsEmpty then Exit;
  end;
  S := IdTCPClient1.IOHandler.ReadLn;
  // use S as needed ...
end;

または:

type
  TMyThread = class(TThread)
  protected
    fClient: TIdTCPClient;
    procedure Execute; override;
  public
    constructor Create(aClient: TIdTCPClient);
  end;

constructor TMyThread.Create(aClient: TIdTCPClient);
begin
  inherited Create(False);
  fClient := aClient;
end;

procedure TMyThread.Execute;
var
  S: String;
begin
  while not Terminated do
  begin
    S := fClient.IOHandler.ReadLn;
    // use S as needed ...
  end;
end;

または、サーバーが実際の Telnet プロトコルをサポートしている場合は、TIdTelnet代わりに Indy のコンポーネントを使用してみてください。

于 2013-08-30T19:09:19.250 に答える