Q&A

  • indy 서버에 접속한 클라이언트가 다운된 경우


평상 시에는 아무런 문제가 없으나,
특수한 상황에서 "B 프로그램"에 접속한 클라이언트 중에 하나 이상이 다운되면, 서버도 같이 다운됩니다.
(다운된다기 보다는 unlock이 안 되네요.
lock->unlock,
lock->unlock, ...,
lock
다음에 unlock이 돼야 하는데, lock에서 멈추네요.)

클라이언트가 다운되자마자 바로 다운되는 건 아니고,
두번째 코드에 있는
IdPeerThread.Connection.WriteLn(XMLTextSending);
이 프로시저를 계속 실행하다가 다운이 되네요.

비정상적으로 연결이 해제돼서, 버퍼가 계속 쌓이는 것인지...
개략적인 소스를 살펴보면 아래와 같습니다.


"A 프로그램"이 다른 프로그램과 공유해야 하는 메시지가 도착하면,
"A 프로그램"이 "UDP"로 "B 프로그램"에게 메시지를 보냅니다.
아래는 "B 프로그램"이 "UDP"로 메시지를 받는 부분입니다.
<!--CodeS-->
procedure TfMain.IdUDPServerUDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  StringStream: TStringStream;
  XMLText: string;
begin
  StringStream := TStringStream.Create('');
  try
    StringStream.CopyFrom(AData, AData.Size);
    XMLText := StringStream.DataString;

    // 접속한 클라이언트에게 메시지를 보낸다.
    SendXMLText(XMLText);
  finally
    FreeAndNil(StringStream);
  end;
end;
<!--CodeE-->

"B 프로그램"이 "UDP"로 수신한 메시지를 접속한 클라이언트들에게 "TCP"로 보냅니다.
아래는 "B 프로그램"에 접속한 클라이언트에게 "TCP"로 메시지를 보내는 부분입니다. (... -> 생략된 부분)
<!--CodeS-->
procedure TfMain.SendXMLText(AXMLText: string);
var
  CreateWheneverUserIn: pCreateWheneverUserIn;
  XMLText             : string;
  XMLTextNotSent      : string;
  XMLTextNotSentLength: Integer;
  XMLTextSending      : string;
  ThreadIndex         : Integer;
  ThreadCount         : Integer;
  UserComputerIP      : string;
  IdPeerThread        : TIdPeerThread;
  ThreadLockList      : TList;
begin
  ...

  XMLTextNotSent := XMLText;
  while (XMLTextNotSent <> '') do
  begin
    XMLTextNotSentLength := Length(XMLTextNotSent);

    // 클라이언트에게 보낼 메시지를 일정한 길이로 가공한다.
    XMLTextSending := Copy(XMLTextNotSent,             1, BUFF_LENG           );
    XMLTextNotSent := Copy(XMLTextNotSent, BUFF_LENG + 1, XMLTextNotSentLength);
    ...
    ThreadLockList := pvThreadList.LockList;
    try
      ThreadCount := ThreadLockList.Count - 1;
      for ThreadIndex := 0 to ThreadCount do
      begin
        CreateWheneverUserIn := ThreadLockList.Items[ThreadIndex];
        ...
        IdPeerThread := TIdPeerThread(CreateWheneverUserIn.CWUI_Thread);
        IdPeerThread.Connection.WriteLn(XMLTextSending);
        ...
      end;
    finally
      if Assigned(ThreadLockList) then
        pvThreadList.UnlockList;
    end;
  end;

  // 로그를 작성한다.
...
<!--CodeE-->
0  COMMENTS