首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TidUDPClient通过代理服务器

TidUDPClient通过代理服务器
EN

Stack Overflow用户
提问于 2017-07-10 06:55:01
回答 1查看 357关注 0票数 0

关于下面的代码,我有一些相关的问题

代码语言:javascript
复制
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发送请求,而不是通过代理服务器发送请求。我怎么才能解决这个问题?我做错什么了?

代理的测试场景如下:

  • 我的PC IP 30.30.30.30
  • UDP服务器10.10.10.10
  • 代理服务器(Socks 5) 20.20.20.20

30.30.30.0/24不能到达10.10.10.10,但20.20.20.20可以。

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

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-10 16:23:46

  1. UDP是无连接的,因此Connected不能告诉您远程对等点是否可访问。 “连接”UDP套接字只需将本地关联分配给对等IP/端口。这样,出站数据包只被发送到该对等点,并且只有从该对等点接收到的数据包被接受。没别的了。没有实际连接,就像在TCP中一样。 与TCP不同的是,发送UDP数据包只是将数据包转储到网络上,因此无法确认数据包已到达对等方。必须在应用层实现Acks。 对于异常,只有在发生实际错误时才会引发异常。在UDP中,无法访问的主机导致套接字错误的唯一方法是,如果网络发送回ICMP数据包以指示无法到达主机。“连接”的UDP套接字将在内部接收此类数据包,并在随后与同一对等方一起读取/发送时开始报告失败。因此,在您的示例中,对Send()的调用永远不会引发一个错误,即无法到达主机,因为它根本不知道。ReceiveString()更有可能报告这些错误,但是按照目前的实现方式,它可能会忽略这些错误,因为它在实际读取套接字之前检查套接字是否是可读的(有一个挂起的UDP数据包)。ICMP数据包可能不会使套接字进入可读状态。 由于您是在ReceiveString()上指定超时,所以如果超时时间过去而没有收到实际的字符串,则只需假定对等点已经消失。
  2. 您的代码正在绕过代理,因为您没有正确设置TransparentProxy。 当您访问TransparentProxy属性时,如果当前没有分配代理组件,则属性getter将创建一个内部TIdSocksInfo对象。TIdSocksInfo有一个默认为svNoSocksVersion属性。由于您试图通过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()将为您处理这个问题。

现在,所有这些都说了,试试这个:

代码语言:javascript
复制
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.
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45005507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档