2016-10-22 13 views
0

これは以前の質問hereのフォローアップの質問です。Delphi 7 Indy 9アプリをIndy 10(II)にアップグレード

多くのコマンドと応答は、区切り文字列としてコード化されています。 Delphi 7では、これらは通常、chr(166)およびchr(167)を使用してコード化されます。

procedure TFormMain.IdTCPServer1InsertAccount(
    ASender: TIdCommand); 
var 
    cmd: String; 
    request: String; 
    Params: TMyStrings; 
    AccountNo, Address, UserName: String; 
begin 
    cmd := 'InsertAccount'; 
    request := Copy(ASender.Rawline, Length(cmd) + 2, Length(ASender.RawLine)); 
    Params := TMyStrings.Create; 
    try 
    AssignDelimited(chr(166), request, Params); 
    AccountNo := Params[0]; 
    Address := replace(char(167), #13#10, Params[1]) 
    UserName := Params[2]; 

パラメータがスペースを含むことができるようになったようです。

// typical client code 
request := edAccountNo.Text + chr(166) + 
    replace(#13, chr(167), replace(#10, '', memoAddress.Lines.Text) + 
    chr(166) + Fusername; 

idTCPClient1.WriteLn('InsertAccount' + space + request); 

今でデルファイ10.1にこのコードを変換する際に:同様に、そのコンテンツメモコントロールから来た自分のキャリッジリターンラインはCHR(167)に置き換えフィードたので、メモの内容がコマンドを終了させずに送ることができるコマンドIndy 10、私はANSIChar(166)で検索と置換chr(166)を行いましたが、Indy 10は127より高いANSICharsを好きではないことをすぐに発見しました。 ? 'sのサーバー

は、このコードをアップグレードするための最善のアプローチは何ですか?おかげさまで

答えて

1

Indy10はUnicodeStringですが、Indy9は認識しません。デルファイ2007およびそれ以前のバージョンではなくAnsiStringを使用するのに対し、デルファイ2009以降のバージョンでは、ネイティブのstringタイプにUnicodeStringを使用しています。

Indy 9は、そのまま8ビットデータとしてAnsiStringデータを送信します。 Indy 10は、AnsiString/UnicodeString文字をcharset変換を使用してバイトに変換し、バイトを送信します。

デフォルトの文字セットはASCIIで、U + 007Fを超えるすべてのUnicode文字は0x3Fに変換されます。パラメータの区切り文字にU + 007Fより大きい文字を使用しているため、デフォルトのASCII文字セットでは?に変換され、プロトコルが破られます。代わりにU + 0001のようなASCII制御文字< U + 0020を使用する方が安全でした。

プロトコルを変更せずにこの問題に対処するには、文字列< - >バイト変換に組み込みの8ビット文字セットを使用するように設定することができます(Unicode文字をU +あなたのプロトコルでは00FF)。これを行うには、次のいずれかにすることができます。クライアントがサーバーに接続した後

  1. IndyTextEncoding_8Bitに接続のIOHandler.DefStringEncodingプロパティを設定します。接続のクライアント側とサーバー側の両方でこれを行います。

    procedure TFormMain.IdTCPServer1Connect(AContext: TIdContext); 
    begin 
        AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding_8Bit; 
    end; 
    

    idTCPClient1.Connect; 
    idTCPClient1.IOHandler.DefStringEncoding := IndyTextEncoding_8Bit; 
    
  2. enc8BitIdGlobal単位でインディのグローバルGIdDefaultTextEncoding変数を設定します。

    procedure TFormMain.FormCreate(Sender: TObject); 
    begin 
        GIdDefaultTextEncoding := enc8Bit; 
    end; 
    
  3. クライアント側でIOHandler.WriteLn()を呼び出すには、そのオプションのAByteEncodingパラメータでIndyTextEncoding_8Bitを渡すことができます。サーバー側では

    idTCPClient1.IOHandler.WriteLn('InsertAccount' + space + request, IndyTextEncoding_8Bit); 
    

    、接続のIOHandler.DefStringEncodingプロパティを割り当てることが最善の、あるいは少なくともGIdDefaultTextEncoding変数を設定することになります。しかし、代替手段として、あなたはTIdCmdTCPServerから新しいコンポーネントを引き出すことができ(あるいはインターポーザクラスを使用して)そのオプションのAByteEncodingパラメータでIndyTextEncoding_8Bitを指定して接続のIOHandler.ReadLn()メソッドを呼び出すようにし、その仮想ReadCommandLine()メソッドをオーバーライドします。

    type 
        TIdCmdTCPServer = class(IdCommandHandlers.TIdCmdTCPServer) 
        protected 
        function ReadCommandLine(AContext: TIdContext): string; override; 
        end; 
    
        TFormMain = class(TForm) 
        IdTCPServer1: TIdCmdTCPServer; 
        ... 
        end; 
    
        ... 
    
        function TIdCmdTCPServer.ReadCommandLine(AContext: TIdContext): string; 
        begin 
        Result := AContext.Connection.IOHandler.ReadLn(IndyTextEncoding_8Bit); 
        end; 
    

参考のために、TCommandHandlerParamDelimiterという特性を持っています。あなたは(それがデフォルトで#32です)#166に設定し、TrueにParseParamsを設定した場合、あなたはあなたのAssignDelimited()機能を削除し、TIdCommandHandlerはそのOnCommandイベントを発射する前にTIdCommand.Paramsプロパティにあなたの区切りのパラメータを解析させることができます。

それも、代わりに各OnCommandイベントハンドラでは、手動でそれを行うの、TIdCommandHandlerから新しいクラスを派生させてさらに一歩進み、#167 -> CRLF変換を処理するために、その仮想DoParseParams()メソッドをオーバーライドすることは可能かもしれません。

+0

ご質問ありがとうございました。 – nolaspeaker

関連する問題