5

Indyクライアントを使用して、サーバーが私(クライアント)に送信しているメッセージを読み取っています。512バイトのデータを一度に送信します。この512バイトのデータは、2つのデータ型(WordとString)で構成されています。たとえば、2バイトのWordを送信し、次に2バイトのWordを送信し、次に50バイトのStringを送信します。私はこの問題に対処するために次のコードを試しています:

var BufferArray : Array[0..512] of Byte;

 if IdTCPClient1.IOHandler.InputBufferIsEmpty then
 begin
      if IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then
      begin
          Edit1.Text := idtcpclient1.IOHandler.ReadBytes(BufferArray ,512, true);
      end;
 end;

Edit1.Text:= idtcpclient1.IOHandler.ReadBytes(BufferArray、512、true);の行でエラーが発生します。エラー:実際のvarパラメータと正式なvarパラメータのタイプは同じである必要があります。

私が使用しているのは正しいアプローチですか。Edit1.Textに512バイト全体を保存したいので、そのデータでやりたいことは何でもします。サーバーから512バイトすべてを取得するのを手伝ってください。

更新:代替アプローチ

私はこのアプローチを使用して単語と文字列の値を読み取ります

WordArray : array[0..5] of word;

 if IdTCPClient1.IOHandler.InputBufferIsEmpty then
 begin
      if IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then
      begin
        i := 0;
        while i < 6 do //Read all the words
        begin
            //Fill WORD data in array
            WordArray[i] :=  (IdTCPClient1.Socket.ReadWord(True));
        end;
      end;
end;

次のような文字列に対する同様のアプローチ

WordArray [i]:=(IdTCPClient1.Socket.ReadString(50));

これは正常に機能していますが、ループ内のすべてのデータを読み取る間、接続を開いたままにする必要があります。接続の間に行くと、すべてが失われ、サーバーにパッケージ全体を再度要求する必要があります。

4

2 に答える 2

1

1: 文字列の文字セットは? それは 1 バイトの windows-1251 ですか? または 2 バイト Unicode UCS-2 ? または可変長 UTF-8 または UTF-16 ?

2: ひもの長さは? 常に 50 ?


バッファの読み取り:

  1. マニュアルを読む
    1.1 http://www.indyproject.org/docsite/html/TIdIOHandler_ReadBytes@TIdBytes@Integer@boolean.html
    1.2 http://www.indyproject.org/docsite/html/TIdIOHandler_ReadSmallInt@Boolean.html 1.3 http: //docwiki.embarcadero.com/Libraries/XE2/en/System.SetString
  2. 型とパラメーターの説明に正確に従ってコードを作成します。
    2.1 ヘッダーの読み取り: 次のような結果になるはずです

    var  Word1, Word2: word;
    
    Word1 := IOHandler.ReadSmallInt(false);   
    Word2 := IOHandler.ReadSmallInt(false);
    
  3. シングルバイト文字列の
    読み取り 3.1 バッファの読み取り
    3.2 バッファを文字列に変換する

    var  Word1, Word2: word;  Buffer: TIdBytes;    
    var s: RawByteString;     
     // or AnsiString; or maybe UTF8String; but probably not UnicodeString aka string
    
    Word1 := IOHandler.ReadSmallInt(false);   
    Word2 := IOHandler.ReadSmallInt(false);
    
    // You should check that you really received 50 bytes,
    // then do something like that:
    
    IOHandler.ReadBytes(Buffer, 50, false);    
    Assert(Length(Buffer)=50);    
    SetString (s, pointer(@Buffer[0]), 50);    
    
  4. 残りを読み続けます - 512 バイトのパケットの 50+2+2 = 54 バイトだけを読みます - もっと多くのデータがあるはずです。

512 = 54*9+26 - ループのように見えるかもしれません - そして 26 バイトの末尾を破棄します。

    var Word1, Word2: word;  Buffer: TIdBytes;    
    var s: RawByteString;     

    for i := 1 to 9 do begin    
      Word1 := IOHandler.ReadSmallInt(false);     
      Word2 := IOHandler.ReadSmallInt(false);  

      IOHandler.ReadBytes(Buffer, 50, false);        
      Assert(Length(Buffer)=50);      
      SetString (s, pointer(@Buffer[0]), 50);    

      SomeOutputCollection.AppendNewElement(Word1, Word2, s);   
    end;   
    IOHandler.ReadBytes(Buffer, 512 - 9*(50+2+2), false); // discard the tail
于 2012-12-12T12:09:41.213 に答える
1

あなたが持っているドキュメントに書かれていることを正確に説明しない限り、あなたに答えるのは難しいです. これまでのところ、512B パケットは 6 ワードと 10x50B 文字列で構成されていることがわかっています。だから、あなたが私たちにもっと教えてくれるまで、これを出発点として考えてください:

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  Buffer: TBytes;
  WordArray: array[0..5] of Word;
  StringArray: array[0..9] of AnsiString;
begin
  if IdTCPClient1.IOHandler.InputBufferIsEmpty then
  begin
    if IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then
      IdTCPClient1.IOHandler.ReadBytes(Buffer, 512, False);

    for I := 0 to High(WordArray) do
    begin
      WordRec(WordArray[I]).Hi := Buffer[I * 2];
      WordRec(WordArray[I]).Lo := Buffer[I * 2 + 1];
    end;
    for I := 0 to High(StringArray) do
      SetString(StringArray[I], PAnsiChar(@Buffer[I * 50 + 12]), 50);

    // here you have the arrays prepared to be processed
  end;
end;
于 2012-12-13T00:58:57.777 に答える