상세 컨텐츠

본문 제목

Delphi Indy UDP Socket의 패킷 손실률

프로그래밍/Delphi

by ryujt 2012. 7. 18. 17:26

본문

예전 프로젝트에서 인디의 UDP 소켓을 이용해서 로컬에서 메시지를 전달하는데, 여러 개의 패킷을 빠르게 전송하면 손실률이 높아지는 문제를 발견한 적이 있습니다.  근래 P2P를 이용해서 프로젝트를 해야 할 일이 있어서 그 동안 그런가 보다 했던 넘을 오늘 다시 살펴보았습니다.


[소스 1] 손실률 50% 이상 발생

procedure TfmMain.btFastClick(Sender: TObject);
var
  Loop: Integer;
begin
  Tag := 0;
  for Loop := 1 to 1000 do begin
    IdUDPServer1.Binding.SendTo('127.0.0.1', 2222, FBuffer);
// 아래는 손실률을 높이게 된다.  아이피만으로 사용 할 경우에는 위의 방식을 사용
//    IdUDPServer1.SendBuffer('127.0.0.1', 2222, FBuffer);
  end;
end;


[소스 2] 손실률 0%, 로컬에서 테스트 함

procedure TfmMain.btSlowClick(Sender: TObject);
var
  Loop: Integer;
begin
  Tag := 0;
  for Loop := 1 to 1000 do begin
    IdUDPServer1.Binding.SendTo('127.0.0.1', 2222, FBuffer);
    Sleep(1);
  end;
end;


[소스 3] 손실률 0.1%, 윈속 유닛 사용

procedure TfmMain.btNativeClick(Sender: TObject);
var
  Loop: Integer;
  SockAddr : TSockAddr;
begin
  FillChar(SockAddr, SizeOf(SockAddr), 0);
  SockAddr.sin_family := AF_INET;
  SockAddr.sin_port := htons(2222);
  SockAddr.sin_addr.S_addr := inet_addr('127.0.0.1');

  Tag := 0;
  for Loop := 1 to 1000 do begin
    SendTo(FSocket, FBuffer[0], Length(FBuffer), 0, SockAddr, SizeOf(TSockAddr));
  end;
end;


귀찮아서 인디를 서버 소켓 두 개를 내려 놓고 테스트를 진행하였습니다.  보내는 쪽을 클라이언 용 컴포넌트로 교체해도 결과는 마찬가지 입니다.


[소스 2]는 이미 "빠르게 전송"이라는 의미가 퇴색했지만, 속도의 문제인지를 파악하기 위해서 검증한 것 입니다.


패킷의 크기는 손실률에 크게 영향을 주지 않으며, 특이하게도 인디 소켓의 경우, IdUDPServer1.BufferSize 크기가 작을 수록 수신률이 향상되었습니다.  (전송하는 패킷의 크기보다 작지 않은 범위에서 설정해야 합니다)


결과적으로 UDP로 다수의 패킷을 빠르게 보내려면 인디는 곤란하다.  해결 방법이 있는 지 소스를 뒤져봤지만, 찾기가 어렵더라 ㅡ.ㅡ;


방법을 찾으시면 저도 좀 ㅡ.ㅡa


인디의 문제일 가능성이 높습니다.  인디를 걷어내고, 윈속으로 서버와 클라이언트 모두 작업 한 후, 충분한 버퍼를 주고 나니 잘 작동합니다.  어느 정도 다듬어 지면 RyuSocket에 포함해서 배포하도록 하겠습니다.


관련글 더보기