본문 바로가기

프로그래밍/Delphi

인디(Indy)를 이용한 Unicode 문자열의 안전한 전송

1. 개요


  Delphi2009 이후부터 기본 문자열이 유니코드를 지원하게 됨에 따라 인디 컴포넌트를 통해 전송되는 UTF8 문자열이 안전하게 전송되지 못하는 문제가 있다. UTF8 문자열을 소켓을 통해 안전하게 전송하는 방법을 찾아 보자


2. 기존처리 방식


    //전송부
    _Client := TIdTCPClient.Create(nil);
    _Client.Host := Host;
    _Client.Port := Port;
    try
      _Client.Connect;
      _Client.IOHandler.WriteLn('Hello World!');
      _Client.IOHandler.WriteLn('안녕하세요!');
    finally
      _Client.free;
    end;

   // 수신부(TIdTCPServer)
  procedure TfrmDebugMain.IdTCPServer1Execute(AContext: TIdContext);
  var
    msg1, msg2 : string;
  begin
    try
      msg1 := AContext.Connection.IOHandler.ReadLn;
      msg2 := AContext.Connection.IOHandler.ReadLn;

      Memo1.Lines.Add(msg1);
      Memo1.Lines.Add(msg2);
    finally

    end;
  end;

  위와 같은 기존 방식으로 처리했을 경우 영문은 정상적으로 나오나 한글 등 UTF8 문자열은 다음과 같이 나타난다.

Hello World!

???? ????!


3. 안전한 UTF8 문자열 전송 방법

  전송시 UTF8 문자열을 Base64로 엔코딩후 전송 및 수신후 다시 디코딩 하는 방식을 사용을 추천함


    //Base64 Encode/Decode 함수

uses
  EncdDecd;

...

function Encode(const Input: string): AnsiString;
var
  utf8: UTF8String;
begin
  utf8 := UTF8String(Input);
  Result := EncdDecd.EncodeBase64(PAnsiChar(utf8), Length(utf8));
end;

function Decode(const Input: AnsiString): string;
var
  bytes: TBytes;
  utf8: UTF8String;
begin
  bytes := EncdDecd.DecodeBase64(Input);
  SetLength(utf8, Length(bytes));
  Move(Pointer(bytes)^, Pointer(utf8)^, Length(bytes));
  Result := string(utf8);
end;

..

// 전송부
    if _Client.Connected then
    begin
      _Client.IOHandler.WriteLn(Encode('Hello World!'));
      _Client.IOHandler.WriteLn(Encode('안녕하세요!'));
    end;

// 수신부
procedure TfrmDebugMain.IdTCPServer1Execute(AContext: TIdContext);
var
  msg1, msg2 : string;
begin
  try
    msg1 := Decode(AContext.Connection.IOHandler.ReadLn);
    msg2 := Decode(AContext.Connection.IOHandler.ReadLn);

    Memo1.Lines.Add(msg1);
    Memo1.Lines.Add(msg2);
  finally
  end;
end;

처리결과

Hello World!

안녕하세요!