0

サーバー側アプリケーションからクライアント側アプリケーションにデータベース レコードを渡そうとしました。クライアント側では、データをTStringsコレクションに保存する必要があります。

複数行フィールドを渡すと、1 つの複数行データ項目ではなく、クライアント側で 2 つの別個のデータ項目を受け取ります! Unicode UTF8 ベースのコマンドでもそれを実行しようとしましたが、残念ながら結果は同じです。

サーバー側コード:

procedure TForm1.IdCmdTCPServer1CommandHandlers0Command(ASender: TIdCommand);
var
  myData: TStrings;
begin
  myData := TStringList.Create;

  myData.Add('12'); // ID
  myData.Add('This is a multi line' + #13#10 + 'description.'); // Descriptions
  myData.Add('Thom Smith'); // Name

  try
    ASender.Context.Connection.Socket.Write(myData, True{, TIdTextEncoding.UTF8});
  finally
    myData.Free;
  end;
end;

myDataサーバー側のデバッグ時の値は次のとおりです。

myData[0] = '12'
myData[1] = 'This is a multi line'#$D#$A'description.'
myData[2] = 'Thom Smith'

クライアント側のコード:

procedure TForm1.Button1Click(Sender: TObject);
var
  myData: TStrings;
begin
  with TIdTCPClient.Create(nil) do
  begin
    Port := 1717;
    Host := 'localhost';

    try
      Connect;
      //IOHandler.DefStringEncoding := TIdTextEncoding.UTF8;

      myData := TStringList.Create;
      try
        SendCmd('greating');
        Socket.ReadStrings(myData, -1{, TIdTextEncoding.UTF8});

        eID.Text    := myData[0];  // ID TEdit
        mDes.Text   := myData[1];  // Descriptions TMemo
        eTelNo.Text := myData[2];  // Name TEdit
      finally
        myData.Free;
      end;
    finally
      Disconnect;
      Free;
    end;
  end;
end;

myDataクライアント側のデバッグ時の値:

myData[0] = '12' myData 1 = 'これは複数行です' myData[2] = '説明。

Telnet の結果:

ここに画像の説明を入力

実は、これは説明フィールドの 2 行目に置き換えられてmyData[2]いるはずです! 'Thom Smith'の後に項目がありませんmyData[2]myData[3]はもうアクセスできません。

Writeこの問題は、Indy'sまたは手順に関連していると思いReadStringsます。ItemCount が 3 として送信されますが、2 つのアイテムが送信されます (1 つが正しく、次は 2 つにビークされています!)。

Write手順myData[1]を 2 行に分割せずに、キャリッジ リターン文字を反対側に渡すにはどうすればよいですか?

どうもありがとう。

4

2 に答える 2

2

TStrings.Text特殊文字を無視したい場合は、ネットで送信する前にそれらをエスケープし、その後でエスケープを解除する必要があります。逃げる方法はたくさんあるので、自分に合った方法を選んでください。

function EscapeString:(String): String --- your choice
function DeEscapeString:(String): String --- your choice

procedure SendEscapedStrings(const socket: TIdSocket; const data: TStrings);
var s: string; temp: TStringList;
begin
  temp := TStringList.Create;
  try
    temp.Capacity := data.Count;
    for s in data do
        temp.Add( EscapeString( s ) );
    socket.Write(temp);
  finally
    temp.Destroy;
  end;
end;

procedure ReadDeescapedStrings(const socket: TIdSocket; const data: TStrings);
var s: string; temp: TStringList;
begin
  temp := TStringList.Create;
  try
    Socket.ReadStrings(temp, -1);
    data.Clear;
    data.Capacity := temp.Count;
    for s in temp do
        temp.Add( DeEscapeString( s ) );
  finally
    temp.Destroy;
  end;
end;

DeEscapeStringここで問題は、何のために何を選択しますEscapeStringか? オプションはたくさんあります。

  • 送信前に文字列をbase64に変換し、読み取り後にbase64から変換することを選択できます
  • escapgin には UUEEncode を、逆エスケープには UUEDecode を選択できます。
  • yEnc を選択できます: http://en.wikipedia.org/wiki/YEnc
  • StrStringToEscapedまたは、非常に単純な関数を選択して、Jedi CodeLib ( http://jcl.sf.net )のユニットStrEscapedToStringから選択することもできます。JclString

どんな逃げ方

提案を求める場合は、生の TCP サーバーを使用しないことをお勧めします。よく知られている標準の HTTP プロトコルがあり、HTTP サーバーと HTTP クライアントの両方を実装する Delphi 用のライブラリが多数あります。また、プロトコル (およびライブラリ) には、暗号化、圧縮、言語サポートなどの決定事項が既にあります。何か問題が発生した場合は、任意の HTTP スニファーを使用して、自分のクライアントまたはサーバーに誰がいるかを確認できます。目。デバッグははるかに簡単です。

始めたばかりの場合は、HTTP + JSON Synopse mORMot ライブラリを調べることをお勧めします。おそらく、ニーズをカバーするでしょう。サンプル サーバー コードは、たとえばhttp://robertocschneiders.wordpress.com/2012/11/22/datasnap-analysis-based-on-speed-stability-tests/から、またはライブラリのデモから取得できます。

次に、生のTCPサーバーを調整する場合は、圧縮されたデータを送信するので、うまく機能します(通常、ネットワークはCPUよりも低速です). http://docwiki.embarcadero.com/CodeExamples/XE5/en/ZLibCompressDecompress_(Delphi)を参照してください。

送信:

  • 1: ネットワークに送信 (int32) - TStringList.Count
  • 2: 実行しているすべての文字列に対して
  • 2.1TStringStream文字列からの作成[i]
  • 2.2 TZCompressionStream 経由で渡す
  • 2.3 圧縮データの送信(int32)サイズ
  • 2.4 データ自体の送信
  • 2.5 一時ストリームの解放

受信

  • 1: ネットから受信 (int32) - パケット数
  • 1.1 ResultStringList.Clear; ResultStringList.Capacity := read_count.
  • 2: 実行しているすべての文字列に対して
  • 2.1 作成TBytesStream
  • 2.2 圧縮データのネット (int32) サイズからの読み取り
  • 2.3 ネットワークから N バイトを BytesStream に読み込む
  • 2.4 TZDecompressionStream を介して TStringStream に解凍する
  • 2.5 ResultStringList.Add( StringStream -> string );
  • 2.6 一時ストリームの解放

ほとんど何も変更したくない場合は、JCL エスケープで十分でしょう。少なくともそれは私にとってはうまくいきましたが、私の仕事は非常に異なっており、ネットワークに関するものではありませんでした. ただし、それらすべてをテストして、それがどのように機能するかを確認することができます.

于 2014-01-20T14:18:15.757 に答える