2017-04-08 39 views
-3

私はから~までTIdTCPClientから多くの暗号化されたRawByteStringデータ(最大500レコード/秒)を転送するための最も速い(株式市場アプリケーション、非常にタイムクリティカルな)ソリューションを探しています。TIdTCPServer/TIdTCPClient:RawByteStringを転送する最も良い方法は?

これを行うにはどうすればよいですか?

ありがとうございます!

編集:私のプロジェクトで

私は、文字列の暗号化にn'Softwareライブラリを使用する必要があります。最速の暗号化メソッドはRawByteStringを返します。理論的には、私は暗号化された文字列のコードページを設定し、それをUTF8エンコードして転送する必要がありますが、すべての試みは失敗しました。

だから私には最も論理的なように見えた:

サーバー:

var 
    rbs: RawByteString; 
begin 
    rbs := EncryptString(AInput, DEFAULT_ENCRYPTION_KEY); 
    SetCodePage(rbs, 65001, true); 
    AContext.Connection.IOHandler.WriteLn(rbs, IndyTextEncoding_UTF8); 
    ... 
end; 

クライアント:UTF-8文字列は単純に間違っているよう

var 
    rbs: string; 
    Output: string; 
begin 
    rbs := IdTCPClient1.IOHandler.ReadLn(IndyTextEncoding_UTF8); 
    Output := DecryptString(rbs, DEFAULT_ENCRYPTION_KEY); 
    ... 
end; 
+0

まあ、それはそうあなたが望むコンポーネントを選択してください使用すると、あまりにも多くのオプションがありません、今はありますか?私たちがあなたのためにドキュメントを読んだり、Googleがあなたのために検索したりしたいのですか? –

+0

バイナリで暗号化された 'RawByteString'をUTF-8文字列として転送することは、速さに関係なく、間違っています。 Indyでバイナリデータを転送する正しい方法は、 'TIdBytes'または' TStream'を使うことです。 'IOHandler'には両方の読み書き方法があります。 Indyの 'RawToBytes()'と 'BytesToRaw()'関数や 'TIdMemoryBufferStream'クラスを見てください。 –

+0

@Remy Lebeauありがとうございました、これはまさに私が探しているものです! –

答えて

0

RawByteString暗号化されたバイナリを転送します、どんなに速くても問題ありません。 Indy 10でバイナリデータを転送する最も良い方法は、代わりにTIdBytesまたはTStreamを使用することです。 IOHandlerには、例えば、両方の方法を書き/読みました:

var 
    rbs: RawByteString; 
begin 
    rbs := EncryptString(AInput, DEFAULT_ENCRYPTION_KEY); 
    AContext.Connection.IOHandler.Write(Int32(Length(rbs))); 
    AContext.Connection.IOHandler.Write(RawToBytes(PAnsiChar(rbs)^, Length(rbs))); 
    ... 
end; 

var 
    buf: TIdBytes; 
    rbs: RawByteString; 
    Output: string; 
begin 
    IdTCPClient1.IOHandler.ReadBytes(buf, IdTCPClient1.IOHandler.ReadInt32); 
    SetLength(rbs, Length(buf)); 
    BytesToRaw(buf, PAnsiChar(rbs)^, Length(rbs)); 
    Output := DecryptString(rbs, DEFAULT_ENCRYPTION_KEY); 
    ... 
end; 

また:あなたが既に持っている場合は

var 
    rbs: RawByteString; 
    strm: TIdMemoryBufferStream; 
begin 
    rbs := EncryptString(AInput, DEFAULT_ENCRYPTION_KEY); 
    strm := TIdMemoryBufferStream.Create(PAnsiChar(rbs), Length(rbs)); 
    try 
    AContext.Connection.IOHandler.LargeStream := False; 
    AContext.Connection.IOHandler.Write(strm, 0, True); 
    finally 
    strm.Free; 
    end; 
    ... 
end; 

var 
    strm: TMemoryStream; 
    rbs: RawByteString; 
    Output: string; 
begin 
    strm := TMemoryStream.Create; 
    try 
    IdTCPClient1.IOHandler.LargeStream := False; 
    IdTCPClient1.IOHandler.ReadStream(strm, -1, False); 
    SetLength(rbs, strm.Size); 
    Move(strm.Memory^, PAnsiChar(rbs)^, Length(rbs)); 
    finally 
    strm.Free; 
    end; 

    { alternatively: 

    SetLength(rbs, IdTCPClient1.IOHandler.ReadInt32); 
    strm := TIdMemoryBufferStream.Create(PAnsiChar(rbs), Length(rbs)); 
    try 
    IdTCPClient1.IOHandler.ReadStream(strm, Length(rbs), False); 
    finally 
    strm.Free; 
    end; 
    } 

    Output := DecryptString(rbs, DEFAULT_ENCRYPTION_KEY); 
    ... 
end; 
+0

素晴らしい!ありがとうございました! –

+0

クライアントが異常終了した場合、Write()がデフォルトのタイムアウト(WriteLnと違って)の後に例外を引き起こさないことは正しいですか?この場合、サーバーは異常に切断されたクライアントをどのように検出できますか? –

+0

'Write ...()'メソッドは 'Write(TIdBytes)'に至り、実際には 'SendDataToTarget()'を呼び出します。したがって、すべてのタイムアウトとエラー処理がすべての書き込み操作に等しく適用されます。しかし、送信は即時の送信ではなく、最終的な送信のためにソケットカーネル内のデータをバッファリングするだけであることに注意してください。したがって、異常に切断されたソケットは、OSが(長時間の)タイムアウト後にソケットを無効にするまで、またはバッファがいっぱいになり書き込みタイムアウトが経過するまで、データを "送信"することができます... –

関連する問題