TidUDPClient通过代理服务器

时间:2017-07-10 06:55:01

标签: delphi proxy udp indy

在下面的代码中我有一些相关的问题

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.
  1. 为什么try...except阻止不会在UDP上发现错误 客户端即使主机不可访问也不是端口关闭,例如IdUDPClient.Connected总是True
  2. 使用代理时,我不确定上面的实现是否正确 因为如果UseProxy为True,则IdUDPClient会尝试直接发送 请求10.10.10.10不通过代理服务器。我怎么解决这个问题?我做错了什么?
  3. 我的代理测试场景如下:

    • 我的电脑知识产权30.30.30.30
    • UDP服务器10.10.10.10
    • 代理服务器(Socks 5)20.20.20.20

    30.30.30.0/24无法到达10.10.10.1020.20.20.20无效。

    1. 如果我的电脑可以直接访问UDP服务器,我将假代理服务器(未使用的IP与随机端口)放到客户端。客户端可以访问不应该到达的UDP服务器,因为代理已关闭。我怎么不能阻止这种情况?

1 个答案:

答案 0 :(得分:1)

  1. UDP是无连接的,因此Connected无法告诉您远程对等方是否可以访问。

    “连接”UDP套接字只是指定与对等IP /端口的本地关联。这样,出站数据包仅发送给该对等体,并且只接受从该对等体接收的数据包。而已。没有实际的连接,比如TCP。

    与TCP不同,发送UDP数据包只是将数据包转发到网络上,没有确认数据包到达对等体。 Acks必须在应用层实现。

    对于异常,只有在发生实际错误时才会引发异常。在UDP中,无法访问的主机导致套接字错误的唯一方法是网络发送回ICMP数据包以指示主机不可访问。 “连接”UDP套接字将在内部接收此类数据包,并在后续读取/发送时使用同一对等方开始报告失败。因此,在您的示例中,对Send()的调用永远不会引发有关无法访问主机的错误,因为它根本不知道。 ReceiveString()报告此类错误的可能性更大,但是当前实现的方式,它可能会忽略它们,因为它在实际读取之前检查套接字是否可读(具有挂起的UDP数据包)。 ICMP数据包可能无法使套接字进入可读状态。

    由于您在ReceiveString()上指定了超时,因此如果超时没有收到实际字符串,则必须假设对等方已消失。

  2. 您的代码正在绕过代理,因为您没有正确设置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.VersionOpenProxy()CloseProxy()TIdUDPClient.Connect()会在TIdUDPClient.Disconnect()启用时为您处理。

  3. 现在,尽管如此,试试这个:

    TransparentProxy