2016-06-28 1 views
0

(Delphi 2009 사용) Indy TidIcmpClient를 사용하여 간단한 네트워크 연결 모니터를 작성하려고합니다. 아이디어는 주소를 ping 한 다음 첨부 된 TidIcmpClient.OnReply 핸들러에서 반환 된 데이터의 양을 테스트하는 것입니다. 응답이> 0 바이트를 포함하면 연결이 성공했음을 알았지 만 TidIcmpClient가 시간 초과되었거나 응답에 0 바이트가 포함 된 경우 링크가 다운 된 것으로 가정합니다.Indy TIdIcmpClient - 시간 초과를 감지하는 방법?

TidIcmpClient의 논리를 이해하는 데 어려움이 있습니다. 'OnTimeout'이벤트가 없습니다.

두 개의 하위 질문에 ...

합니까 TidIcmpClient.OnReply 어쨌든 호출되는, 하나의 (a) 데이터가 수신 될 때 또는 (b) 제한 시간에 도달하면, 중 먼저?

0 바이트가 포함 된 시간 초과 기간 내에 실제 응답 시간 초과로 인해 0 바이트 응답을 구별 할 수 있습니까? 즉

확인 코드의 일종이다하거나

procedure TForm1.IdIcmpClient1Reply(ASender: TComponent; const AReplyStatus: TReplyStatus); 
begin 
if IdIcmpClient1.ReplyStatus.BytesReceived = 0 then 
    //we must have timed out, link is down 
else 
    //got some data, connection is up 
end; 

procedure DoPing; 
begin 
IdIcmpClient1.ReceiveTimeout := 200; 
IdIcmpClient1.Host := '8.8.8.8'; 
IdIcmpClient1.Ping; 
end; 

답변

6

Ping() 종료하면 ReplyStatus 속성은 OnReply 이벤트 (당신이 매개 변수를 무시하는)의 AReplyStatus 매개 변수에 전달되는 것과 같은 정보가 포함되어 있습니다. Ping()OnReply 이벤트를 사용하기 전에 실제로 종료하기 전에 OnReply 처리기를 호출하고 ReplyStatus 속성을 전달하므로 실제로는 OnReply 이벤트를 사용하지 않아도됩니다. 코드를 불필요하게 분해하는 것뿐입니다.

procedure DoPing; 
begin 
    IdIcmpClient1.ReceiveTimeout := 200; 
    IdIcmpClient1.Host := '8.8.8.8'; 
    IdIcmpClient1.Ping; 
    // process IdIcmpClient1.ReplyStatus here as needed... 
end; 

즉, 사용자는 ReplyStatus 데이터를 올바르게 처리하지 못합니다. BytesReceived 필드는 ping이 실패하더라도 0보다 클 수 있습니다. 이름에서 알 수 있듯이 ICMP 응답에 대해 실제로 몇 바이트가 수신되었는지보고합니다. ICMP는 다양한 종류의 응답을 정의합니다. ReplyStatusType 필드는 실제로 수신 된 응답 유형으로 설정됩니다. 핑이 성공

type 
    TReplyStatusTypes = (rsEcho, 
    rsError, rsTimeOut, rsErrorUnreachable, 
    rsErrorTTLExceeded,rsErrorPacketTooBig, 
    rsErrorParameter, 
    rsErrorDatagramConversion, 
    rsErrorSecurityFailure, 
    rsSourceQuench, 
    rsRedirect, 
    rsTimeStamp, 
    rsInfoRequest, 
    rsAddressMaskRequest, 
    rsTraceRoute, 
    rsMobileHostReg, 
    rsMobileHostRedir, 
    rsIPv6WhereAreYou, 
    rsIPv6IAmHere, 
    rsSKIP); 

경우, ReplyStatusTypersEcho 될 것이며, ReplyData 필드 Ping()ABuffer 매개 변수에 전달 된 (선택 사항) 데이터가 포함됩니다 : 정의 (20 개) 값이 있습니다. FromIpAddressToIpAddress 필드에도주의를 기울여 예상되는 대상 시스템에서 실제로 응답이 나오는지 확인해야 할 수 있습니다.

시간 초과가 발생하면 ReplyStatusTypersTimeOut이됩니다.

이 시도 :

procedure DoPing; 
begin 
    IdIcmpClient1.ReceiveTimeout := 200; 
    IdIcmpClient1.Host := '8.8.8.8'; 
    IdIcmpClient1.Ping; 
    if IdIcmpClient1.ReplyStatus.ReplyStatusType = rsEcho then 
    begin 
    // got some data, connection is up 
    end 
    else if IdIcmpClient1.ReplyStatus.ReplyStatusType = rsTimeout then 
    begin 
    // have a timeout, link is down 
    end 
    else 
    begin 
    // some other response, do something else... 
    end; 
end; 
+0

매우 유용한 응답 레미. 그것은 그것을 충분히 설명합니다. – user3209752

+0

@RemyLebeau 왜 소켓 오류 액세스가 거부되었습니다 10013? 방화벽이 다운되었습니다. – grinner

+0

확인 : https://stackoverflow.com/questions/13611525/does-indy-ping-require-uac-elevation – grinner

0

IdIcmpClient의 companent이 OnReply 이벤트가 시간 초과 또는하지 않을 경우 내가 말할 수있는 다른 일을 어떻게해야합니까. 이 이벤트에는 TReplyStatus 유형의 AReplyStatus 매개 변수가 있습니다. TReplyStatus에는 ReplyStatusType 속성이 있습니다. 이 속성의 형식은 TReplyStatusTypes입니다. TReplyStatusTypes에는 rsTimeOut 값이 있습니다. OnReply 이벤트에 코드를 추가하고 시간 초과 또는 기타 오류를 확인하십시오.

procedure TForm1.IdIcmpClient1Reply(ASender: TComponent; 
    const AReplyStatus: TReplyStatus); 
begin 
    if AReplyStatus.ReplyStatusType = rsTimeOut then 
    begin 
    //do someting on timeout. 
    end; 
end; 
관련 문제