在下面的代码中我有一些相关的问题
var
UseProxy : Boolean = True;
....
var
IdUDPClient : TIdUDPClient;
sText : string;
begin
IdUDPClient := TIdUDPClient.Create(nil);
try
IdUDPClient.Host := '10.10.10.10';
IdUDPClient.Port := 5555;
if UseProxy then begin
IdUDPClient.TransparentProxy.Enabled := True;
IdUDPClient.TransparentProxy.Host := '20.20.20.20';
IdUDPClient.TransparentProxy.Port := 8080;
IdUDPClient.OpenProxy;
end;
try
IdUDPClient.Connect;
except
Writeln('Connect Error.');
end;
if IdUDPClient.Connected then
Writeln('Connected')
else begin
Writeln('Not Connected');
Exit;
end;
try
IdUDPClient.Send('Foo');
try
sText := IdUDPClient.ReceiveString(1000);
Writeln('Received: ', sText);
except
Writeln('Receive Error.');
end;
except
Writeln('Send Error.');
end;
if UseProxy then
IdUDPClient.CloseProxy;
finally
IdUDPClient.Free;
end;
Readln;
end.
try...except
阻止不会在UDP
上发现错误
客户端即使主机不可访问也不是端口关闭,例如IdUDPClient.Connected
总是True
?UseProxy
为True,则IdUDPClient会尝试直接发送
请求10.10.10.10
不通过代理服务器。我怎么解决这个问题?我做错了什么? 我的代理测试场景如下:
30.30.30.30
10.10.10.10
20.20.20.20
30.30.30.0/24
无法到达10.10.10.10
但20.20.20.20
无效。
答案 0 :(得分:1)
UDP是无连接的,因此Connected
无法告诉您远程对等方是否可以访问。
“连接”UDP套接字只是指定与对等IP /端口的本地关联。这样,出站数据包仅发送给该对等体,并且只接受从该对等体接收的数据包。而已。没有实际的连接,比如TCP。
与TCP不同,发送UDP数据包只是将数据包转发到网络上,没有确认数据包到达对等体。 Acks必须在应用层实现。
对于异常,只有在发生实际错误时才会引发异常。在UDP中,无法访问的主机导致套接字错误的唯一方法是网络发送回ICMP数据包以指示主机不可访问。 “连接”UDP套接字将在内部接收此类数据包,并在后续读取/发送时使用同一对等方开始报告失败。因此,在您的示例中,对Send()
的调用永远不会引发有关无法访问主机的错误,因为它根本不知道。 ReceiveString()
报告此类错误的可能性更大,但是当前实现的方式,它可能会忽略它们,因为它在实际读取之前检查套接字是否可读(具有挂起的UDP数据包)。 ICMP数据包可能无法使套接字进入可读状态。
由于您在ReceiveString()
上指定了超时,因此如果超时没有收到实际字符串,则必须假设对等方已消失。
您的代码正在绕过代理,因为您没有正确设置TransparentProxy
。
当您访问TransparentProxy
属性时,如果当前未分配代理组件,则属性getter将创建内部TIdSocksInfo
对象。 TIdSocksInfo
的{{1}}属性默认为Version
。由于您尝试通过SOCKS v5代理进行连接,因此需要将svNoSocks
设置为Version
而不是:
svSocks5
if UseProxy then begin
(IdUDPClient.TransparentProxy as TIdSocksInfo).Version := svSocks5; // <--
IdUDPClient.TransparentProxy.Host := '20.20.20.20';
IdUDPClient.TransparentProxy.Port := 8080;
end;
属性设置器根本不与TransparentProxy.Enabled
一起使用,它是一个无操作。但是,TIdSocksInfo
属性getter返回True / False,具体取决于Enabled
属性的值。
您无需手动拨打TIdSocksInfo.Version
和OpenProxy()
,CloseProxy()
和TIdUDPClient.Connect()
会在TIdUDPClient.Disconnect()
启用时为您处理。
现在,尽管如此,试试这个:
TransparentProxy