2012-12-12 19 views
5

Indyクライアントを使用して、サーバーが私に送信しているメッセージ(クライアント)を読み取っています。私は512バイトのデータを一度に送信します。この512バイトのデータは、2つのデータ型(WordおよびString)で構成されています。たとえば、2バイトのWordを送信し、次に2バイトのWordを送信し、次に50バイトのStringなどを送信します。DelphiでIndy Clientを使用しているサーバーからすべてのバイトを読み取る方法は?

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パラメータの型は同じでなければなりません。

私が使用しているアプローチは正しいですか? Edit1.Textに512バイト全体を保存して、そのデータで何をしたいのかを行います。サーバーから512バイトすべてを手に入れてください。

更新:交互アプローチ

私は単語や文字列を読み取るために、このアプローチを使用しています

WordArray [i]のような文字列のための

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; 

同様のアプローチ値:=(IdTCPClient1を。 Socket.ReadString(50));

うまく動作しますが、ループ内のすべてのデータを読み取っている間は接続を開いたままにしておく必要があります。接続の間にあれば、私はすべてを失い、サーバーからパッケージ全体を再度要求しなければなりません。

+1

'BufferArray'に動的配列を使用し、宣言を' var BufferArray:TBytes; 'に変更してください。 – TLama

+0

はい、同じでした。出来た。ありがとう。今私はさらに問題があります。このBufferArrayをどのように反復処理できますか?私はそれを文字列配列にすべて保存したい。 –

+0

@TLama - 私の質問が更新されました。私の新しいアプローチは正しいのですか? –

答えて

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; 
+0

大丈夫です、これを試してみましょう。それがうまくいけば、私はあなたに大きな感謝を与えるでしょう –

+0

私はそれが動作することを期待していない、単語の部分はバイトをスワップしている可能性があり、文字列部分はANSI文字を受け取っていると期待している、 ANSI、Unicodeの場合、どのように文字列がサーバーから送信されるのかはまったく分かりません。どのように終了しますか(これは珍しいことですが、わかりません)。私はまた、これらの言葉がどのようにバイトオーダーで送られるかを知らない。あなたはこれらの情報を追加して、それによって答えを洗練させなければなりません。 – TLama

+0

それがうまくいかない場合、パケットの正確なフォーマットを示す単語文書をあなたと共有します。 –

1

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

2:文字列の長さはどのくらいですか?いつも50?


バッファを読み出す:

  1. をマニュアル 1.1 http://www.indyproject.org/docsite/html/[email protected]@[email protected]
    1.2 http://www.indyproject.org/docsite/html/[email protected] 1.3 http://docwiki.embarcadero.com/Libraries/XE2/en/System.SetString
  2. 正確なタイプ及びパラメータの説明次のコードを作る
    を読み取ります。ヘッダを読み取り
    2.1:文字列

    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);  
    
  3. にバッファを変換バッファ
    3.2読み出しシングルバイト文字列
    3.1を読み取る

    var Word1, Word2: word; 
    
    Word1 := IOHandler.ReadSmallInt(false); 
    Word2 := IOHandler.ReadSmallInt(false); 
    
  4. ようなものをもたらすべき残りを読み続けます - 50 + 2 + 2 = 54バイトの512バイトパケットしか読まない - より多くのデータがあるはずです。

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 
+0

@TLama ReadStringはUnicodeStringを返します。トピックのスターターは約50バイトを語った。潜在的な混乱があります - と私は答えのヘッダーに記載されています。しかし、話題のスターターがオリジナルの "50バイト"の主張を維持する限り、それは私のように見えます。 Indyが 'ReadAnsiString(const codepage:word; const length:cardinal);メソッドを導入するまで、 –

+0

ええ、私はそれを認識し、コメントを削除しました。 – TLama

+0

自分自身を修正して、私が512パケットをどのように解析したいかについて詳しく説明しましょう。私は2バイトの6ワードがあり、次に50バイトのストリングがあるというこのパケットの文書を持っています。今私は異なる単語配列と異なる文字列配列の文字列に単語を格納する必要があります。今、これらのものをこのパケットからどのように抽出できますか? –

関連する問題