关于下面的代码,我有一些相关的问题
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总是TrueUseProxy为True,则IdUDPClient尝试直接向10.10.10.10发送请求,而不是通过代理服务器发送请求。我怎么才能解决这个问题?我做错什么了?代理的测试场景如下:
30.30.30.3010.10.10.1020.20.20.2030.30.30.0/24不能到达10.10.10.10,但20.20.20.20可以。
发布于 2017-07-10 16:23:46
Connected不能告诉您远程对等点是否可访问。
“连接”UDP套接字只需将本地关联分配给对等IP/端口。这样,出站数据包只被发送到该对等点,并且只有从该对等点接收到的数据包被接受。没别的了。没有实际连接,就像在TCP中一样。
与TCP不同的是,发送UDP数据包只是将数据包转储到网络上,因此无法确认数据包已到达对等方。必须在应用层实现Acks。
对于异常,只有在发生实际错误时才会引发异常。在UDP中,无法访问的主机导致套接字错误的唯一方法是,如果网络发送回ICMP数据包以指示无法到达主机。“连接”的UDP套接字将在内部接收此类数据包,并在随后与同一对等方一起读取/发送时开始报告失败。因此,在您的示例中,对Send()的调用永远不会引发一个错误,即无法到达主机,因为它根本不知道。ReceiveString()更有可能报告这些错误,但是按照目前的实现方式,它可能会忽略这些错误,因为它在实际读取套接字之前检查套接字是否是可读的(有一个挂起的UDP数据包)。ICMP数据包可能不会使套接字进入可读状态。
由于您是在ReceiveString()上指定超时,所以如果超时时间过去而没有收到实际的字符串,则只需假定对等点已经消失。TransparentProxy。
当您访问TransparentProxy属性时,如果当前没有分配代理组件,则属性getter将创建一个内部TIdSocksInfo对象。TIdSocksInfo有一个默认为svNoSocks的Version属性。由于您试图通过SOCKS v5代理进行连接,因此需要将Version设置为svSocks5:
如果UseProxy开始(IdUDPClient.TransparentProxy as TIdSocksInfo).Version := svSocks5;// <-- IdUDPClient.TransparentProxy.Host := '20.20.20.20';IdUDPClient.TransparentProxy.Port := 8080;
TransparentProxy.Enabled属性设置程序根本不与TIdSocksInfo一起使用,它是一个非操作。但是,Enabled属性getter根据TIdSocksInfo.Version属性的值返回True/False。
而且您不需要手动调用OpenProxy()和CloseProxy(),当启用TransparentProxy时,TIdUDPClient.Connect()和TIdUDPClient.Disconnect()将为您处理这个问题。现在,所有这些都说了,试试这个:
var
UseProxy : Boolean = True;
...
var
IdUDPClient : TIdUDPClient;
IdSocksInfo : TIdSocksInfo;
sText : string;
begin
IdUDPClient := TIdUDPClient.Create(nil);
try
IdUDPClient.Host := '10.10.10.10';
IdUDPClient.Port := 5555;
if UseProxy then begin
IdSocksInfo := TIdSocksInfo.Create(IdUDPClient);
IdSocksInfo.Version := svSocks5;
IdSocksInfo.Host := '20.20.20.20';
IdSocksInfo.Port := 8080;
IdUDPClient.TransparentProxy := IdSocksInfo;
end;
try
IdUDPClient.Connect;
except
on E: Exception do begin
Writeln('Connect Error: ', E.Message);
Exit;
end;
end;
try
Writeln('Connected.');
try
IdUDPClient.Send('Foo');
except
on E: Exception do begin
Writeln('Send Error: ', E.Message);
Exit;
end;
end;
try
sText := IdUDPClient.ReceiveString(1000);
if sText <> '' then
Writeln('Received: ', sText)
else
Writeln('Nothing Received after 1 second.');
except
on E: Exception do begin
Writeln('Receive Error: ', E.Message);
end;
end;
finally
IdUDPClient.Disconnect;
end;
finally
IdUDPClient.Free;
end;
end.https://stackoverflow.com/questions/45005507
复制相似问题