FreePascal Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
FreePacal 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

FreePascal 강좌/문서
[9] 라자루스를 이용한 업무 프로그램 개발 - 8
어느좋은날 [freepascal] 577 읽음    2020-06-13 22:44
2. 테스트 클라이언트 만들기
2-1. DataModule 선언부 및 이벤트

테스트 클라이언트를 만들기 위해 New 메뉴의 Project 트리에서 Application을 선택한다. 컴파일 옵션은 앞의 미들웨어 서버와 동일하게 설정해서 실행 파일의 용량이 커지지않게 한다. 메인 폼의 이름을 적당히 정하고 Position을 지정한다.(※ poScreenCenter로 지정해서 화면 가운데에서 실행 됨.)

이번에는 New메뉴에서 TDataModule을 선택해서 생성한다. TDataModule은 서버와의 데이터 송/수신 및 클라이언트에서 사용하는 공통 사항들을 묶어서 관리하기위한 용도로 사용한다. TDataModule의 Name은 "dmSIMLaz"로 정하고 아래 화면과 같이 컴퍼넌트를 배치한 후 Name을 지정하고 "simlaz_dm.pas" 파일로 저장한다.



TDataModule에 ini File 처리를 위한 "IniFiles"와 TCP/IP 통신용 공통변수 및 함수를 가지고 있는 "simlaz_lib", SHA256 값을 가져오기위한 "IdHash" / "IdHashSHA" / "IdSSLOpenSSLHeaders", Lock 처리를 위한 "syncobjs", XML 처리를 위한 "XMLDatapacketReader" 등을 uses 구문에 추가 한다.
unit simlaz_dm;

{$mode objfpc}{$H+}

interface

uses
  ..., IniFiles, syncobjs, simlaz_lib, XMLDatapacketReader, IdGlobal, IdHash, IdHashSHA, IdSSLOpenSSLHeaders;


서버와 통신을 하거나 클라이언트 프로그램 전반에 사용될 변수와 함수들을 정의한다.
  { TdmSIMLaz }

  TdmSIMLaz = class(TDataModule)
    IdAntiFrz: TIdAntiFreeze;
    IdTCPConn: TIdTCPClient;
    qrTmp: TBufDataset;
    tmDummy: TTimer;
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
    procedure IdTCPConnConnected(Sender: TObject);
    procedure IdTCPConnDisconnected(Sender: TObject);
    procedure tmDummyTimer(Sender: TObject);
  private

  public
    u_Lock: TCriticalSection;
    u_Encoding: IIdTextEncoding;

    u_uid, // 사용자ID
    u_uname: string; // 사용자명

    u_admin_flag: Boolean; // 관리자 여부

    function UF_SIMLazSnd(ACmd: UInt8; var ACont: TIdBytes): Boolean; // 데이터 전송
    function UF_SIMLazRcv(var ACmd: UInt8; out ACont: TIdBytes): Boolean; // 데이터 수신

    function UF_SIMLazSHA(const AValue: string): string; // SHA256

    function UF_SIMLazDummy: Boolean; // Dummy
    function UF_SIMLazList: string; // 접속자 목록
    function UF_SIMLazVer(AID: string): string; // 버전 정보
    function UF_SIMLazLogin(AID, APasswd: string): Boolean; // 로그인
    function UF_SIMLazExec(AQuery: string): Int32; // Query 실행

    procedure UP_SIMLazOpen(ADataSet: TCustomBufDataset; AQuery: string; const ALoadFields: Boolean); // 데이터 가져오기
    procedure UP_SIMLazFile(AID, AFileName: string); // 파일 가져오기
  end;


DataModule이 생성될 때 Lock 처리를 위한 객체를 생성하고 접속할 서버의 IP와 Port를 ini 파일에서 가져와 Indy TCP Client에 할당하고 접속한다. DataModule이 Destroy될 때 서버에 접속이 되어있으면 접속을 종료하고 사용했던 Lock 객체를 Free 시킨다. 사용자 컴퓨터에 설치할 때 미들웨어 서버의 IP나 Port 정보를 노출시키고 싶지 않을 때는 INI 파일의 데이터를 암호화해서 저장해야 한다. (※ 본 예제에서는 INI 파일의 암호화 처리는 하지 않음.)
procedure TdmSIMLaz.DataModuleCreate(Sender: TObject);
begin
  if IdTCPConn.Connected then IdTCPConn.Disconnect;

  u_Lock := TCriticalSection.Create;
  u_Encoding := IndyTextEncoding_UTF8;

  with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'simlaz_client.ini') do
  begin
    try
      IdTCPConn.Host := ReadString('Setup', 'IP', '');
      IdTCPConn.Port := ReadInteger('Setup', 'Port', 0);
    finally
      Free;
    end;
  end;
  IdTCPConn.Connect;
end;

procedure TdmSIMLaz.DataModuleDestroy(Sender: TObject);
begin
  if IdTCPConn.Connected then IdTCPConn.Disconnect;
  FreeAndNil(u_Lock);
end;


서버에 접속한 후에는 서버로부터 접속되었다는 정보를 수신하고 제대로 수신 되었으면 접속 유지를 위한 Dummy 전송용 타이머를 구동시킨다. 접속 종료후에는 Dummy 전송용 타이머를 종료시킨다.
procedure TdmSIMLaz.IdTCPConnConnected(Sender: TObject);
var
  l_Cmd: UInt8;
  l_Data: TIdBytes;
begin
  l_Data := nil;
  l_Cmd := smlc_CONNECT;
  if UF_SIMLazRcv(l_Cmd, l_Data) then
  begin
    tmDummy.Tag := 0;
    tmDummy.Enabled := True;
  end
  else IdTCPConn.Disconnect;
end;

procedure TdmSIMLaz.IdTCPConnDisconnected(Sender: TObject);
begin
  tmDummy.Enabled := False;
end;


Dummy 타이머는 1분마다 체크하게끔 Interval을 60000으로 설정하고 5분마다 Dummy 데이터를 보낸다.
procedure TdmSIMLaz.tmDummyTimer(Sender: TObject);
begin
  tmDummy.Tag := tmDummy.Tag + 1;
  if tmDummy.Tag >= 5 then
  begin
    tmDummy.Enabled := False;
    try
      if UF_SIMLazDummy then tmDummy.Enabled := True;
      tmDummy.Tag := 0;
    except
      IdTCPConn.IOHandler.InputBuffer.Clear;
      IdTCPConn.Disconnect;
    end;
  end;
end;

// Dummy
function TdmSIMLaz.UF_SIMLazDummy: Boolean;
var
  l_Cmd: UInt8;
  l_Data: TIdBytes;
begin
  Result := False;
  if not IdTCPConn.Connected then
  begin
    MessageDlg(Application.Title, ERR_SIMLAZ302, mtError, [mbOK], 0);
    Exit;
  end;

  u_Lock.Enter;
  try
    l_Data := nil;
    l_Cmd := smlc_DUMMY;
    if not UF_SIMLazSnd(l_Cmd, l_Data) then Exit;
    l_Data := nil;
    Result := UF_SIMLazRcv(l_Cmd, l_Data);
  finally
    u_Lock.Leave;
  end;
end;

+ -

관련 글 리스트
9 라자루스를 이용한 업무 프로그램 개발 - 8 어느좋은날 577 2020/06/13
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.