Q&A

  • Indy를 이용해서 소켓프로그램을 만들었는데...
client에서 server로 query문장을 날리면 server가 받은 query를 실행해서

자료를 화일로 만들게
1  COMMENTS
  • Profile
    구창민 2001.07.25 06:15
    안녕하세요~ 구창민입니다.



    Indy에서는 fork 를 지원하지 않습니다.



    대신 거의 유사하게 동작하는 쓰레드를 지원합니다.



    아래 답변은 일전에 권용길님이 답변하신 내용인데, 님의



    질문과 일맥하는 내용인거 같아 올려드립니다.



    보시고, 항상 즐거운 프로그래밍 하시길~



    ===============================================================



    [첫번째 방법]

    OnExecute에서 테이블을 생성하고 소멸시켜 각 쓰레드마다

    다른 테이블 컴포넌트를 사용하게 하면 됩니다.

    단점은 테이블 생성, 내부적인 DB연결, 소멸로 인한 오버헤드입니다.

    장점은 각 DB Query가 여러쓰레드에 의해서 동시에 실행되므로

    병렬성이 좋아진다는 거지요.



    [두번째 방법]

    인디의 OnExecute는 개별 쓰레드 상에서 실행되는 건 아시죠?

    델파이의 Thread에는 메소드 호출을 동기화해서 특정 메소드가

    여러 쓰레드에 의해 동시해 호출되는 일을 없도록 해주는 메소드가

    있습니다. 이 놈이 Syncronize인데 이놈의 인자로 동기화 시킬 필요가

    있는 즉, 한 번에 한 개의 쓰레드만 실행시키고 싶은 메소드를 전달합니다.

    이것은 메소드를 메인쓰레드에서 실행하기 때문에 가능한 일입니다.



    예제를 만들어 드리고 싶지만, 바빠서 말로 대신 합니다.

    아래는 테스트하지 않은 예제이므로 오타, 버그 등이 숨어 있을 수 있음다.



    var

    TForm1 = class(TForm)

    ...

    FUserInfo : TUserInfo ; // 사용자 정보 저장소, 구조체로 직접 정의하세요.

    procedure UpdateUsernfo;

    ...

    end;



    // 이 메소드는 Syncronize에 의해 호출되므로

    // 한 번에 한 개의 쓰레드에 의해 실행된다.

    procedure TForn1.UpdateUserInfo;

    begin

    // FUserInfo 데이터를 읽어 필요한 작업을 한다.

    // 사용자를 찾고 IP를 변경하는 등...

    end;



    procedure TForn1.IdTCPServer1OnExecute( AThread : TIdThread );

    begin

    // FUserInfo에 필요한 데이터를 써 넣는다.

    AThread.Syncronize( UpdateUserInfo );

    end;



    여기서 유의할 점은....

    Syncronize의 인자로 오는 함수는 그 자체가 인자가 없는 프로시저이기

    때문에 인자로 자료를 전달할 수 없습니다.

    따라서, 위 처럼 멤버 필드를 하나 만들어 자료를 전달합니다.

    이런 모습을 쓰레드끼리 서로 데이터를 통해 연동한다고해서

    '데이터 바인딩'이라고 합니다.



    또한 OnExecute는 우리 보통 생각과는 달리 Connection이 유지되고 있는 한

    계속해서 반복적으로 호출됩니다. 따라서, OnExecute 함수에서

    단번에 모든 처리를 다했다면 리턴하기 전에

    AThread.Connectino.Disconnected를 호출하는 것이 올바릅니다.





    [보너스! 아래 방법이 않 통한 이유]

    크리티컬 섹션도 한 방법입니다만,

    여기서 제대로 작동하지 않은 이유는...



    크릭티컬 섹션이 항상 생성 되어 있어야 하는데,

    쓰레드가 서로 생성했다가 지우기 때문입니다.



    InitializeCriticalSection를 Initialization 파트에

    DeleteCriticalSection을 finalization 파트에 두면 잘 될 겁니다.



    [정리]

    마지막 두 방법은 DB 질의가 동시에 수행되지 않기 때문에

    쓰레드의 장점을 살리지 못할 수 있습니다.

    따라서, 직렬화(혹은 크리티컬 섹션)가 필요한 부분을 최소화하여

    병렬 실행의 장점을 살리는 것이 좋습니다.



    방법1을 사용하더라도 Query를 Query Pool 같은 곳에 미리 여러개 생성해놓고

    재사용 한다면 간단하면서도 좋은 성능을 낼 수 있습니다.



    이상이 제가 드릴 수 있는 거의 모든 정보입니다.









    김초보 wrote:

    > client에서 server로 query문장을 날리면 server가 받은 query를 실행해서

    > 자료를 화일로 만들게