(使用Delphi 2009)我尝试使用Indy TidIcmpClient编写一个简单的网络连接监视器。想法是ping一个地址,然后在附加的TidIcmpClient.OnReply处理程序内测试返回了多少数据。如果回复包含> 0字节,然后我知道连接成功,但如果TidIcmpClient超时或回复包含0字节,我将假设链接已关闭
我很难理解TidIcmpClient的逻辑,因为没有' OnTimeout'事件
两个子问题......
无论如何都要调用TidIcmpClient.OnReply,(a)收到数据时还是(b)达到超时时(以先到者为准)?
如何区分零字节回复,因为超时时间内的实际回复超时,恰好包含零字节(或者不会发生这种情况)?
换句话说,这种代码是好的,还是我需要做些别的事来告诉它是否超时
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;
答案 0 :(得分:8)
当Ping()
退出时,ReplyStatus
属性包含传递给AReplyStatus
事件的OnReply
参数的相同信息(您忽略该参数)。 Ping()
只需在退出前调用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
数据。即使ping失败,BytesReceived
字段也可以大于0。顾名思义,它只是报告ICMP响应实际接收的字节数。 ICMP定义了许多不同类型的响应。 ReplyStatusType
字段将设置为实际收到的响应类型。定义了20个值:
type
TReplyStatusTypes = (rsEcho,
rsError, rsTimeOut, rsErrorUnreachable,
rsErrorTTLExceeded,rsErrorPacketTooBig,
rsErrorParameter,
rsErrorDatagramConversion,
rsErrorSecurityFailure,
rsSourceQuench,
rsRedirect,
rsTimeStamp,
rsInfoRequest,
rsAddressMaskRequest,
rsTraceRoute,
rsMobileHostReg,
rsMobileHostRedir,
rsIPv6WhereAreYou,
rsIPv6IAmHere,
rsSKIP);
如果ping成功,ReplyStatusType
将为rsEcho
,ReplyData
字段将包含传递给ABuffer
参数的Ping()
参数FromIpAddress
。您可能还需要关注ToIpAddress
和ReplyStatusType
字段,以确保响应实际来自预期的目标计算机。
如果发生超时,rsTimeOut
将改为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;
。
试试这个:
var url = 'https://ct.soa-gw.canadapost.ca/rs/ship/price';
var auth = 'Basic BASE64ENCODEDUSERNAMEANDPASSWORD';
var xml = '' +
'<?xml version="1.0" encoding="utf-8"?>' +
'<mailing-scenario xmlns="http://www.canadapost.ca/ws/ship/rate-v3">' +
'<customer-number>1234567</customer-number>' +
'<parcel-characteristics><weight>1.0</weight></parcel-characteristics>' +
'<services><service-code>DOM.XP</service-code></services>' +
'<origin-postal-code>K2B8J6</origin-postal-code>' +
'<destination><domestic><postal-code>J0E1X0</postal-code></domestic></destination>' +
'</mailing-scenario>';
var header = {
'Authorization': auth,
'Content-Type': 'application/soap+xml;application/vnd.cpc.ship.rate-v3+xml',
'Accept-language': 'en-CA',
'Accept': 'application/vnd.cpc.ship.rate-v3+xml'
};
var r = nlapiRequestURL(url, xml, header, null, 'POST');
console.log(r.code[0]);
console.log(r.body);
答案 1 :(得分:0)
IdIcmpClient companent有OnReply事件。此事件的AReplyStatus参数类型为TReplyStatus。 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;