【问题标题】:Connecting to ruby tcpserver from delphi using indy使用 indy 从 delphi 连接到 ruby​​ tcpserver
【发布时间】:2017-06-22 15:08:47
【问题描述】:

我得到了以下示例(作者:Matt S)在 cmd 提升模式下运行:How do you test the Push Notification feedback service?

我可以使用“telnet localhost 2196”连接到这个 ruby​​ 服务器,它会开始向 telnet 客户端发送数据就好了。

但是,如果我尝试将其用于 delphi,则使用 indy:

    TcpClient := TIdTcpClient.Create(nil);
    TcpClient.Host := 'localhost';
    TcpClient.Port := 2196;
    TcpClient.Connect;

我收到以下错误:Socket Error # 10061 Connection denied 一旦调用“Connect”。好像找不到 tcp 服务器。

我在这里可能做错了什么?

【问题讨论】:

    标签: ruby delphi apple-push-notifications client tcpserver


    【解决方案1】:

    该错误表示服务器没有监听127.0.0.1。服务器可能正在侦听其他本地 IP,而不侦听 127.0.0.1

    localhost 不一定只指127.0.0.1。通过gethostbyname()getaddrinfo() 进行的查找查询可以将localhost 解析为实际的本地IP,然后telnet 会尝试连接,直到成功为止。

    但 Indy 目前仅将 localhost 视为 127.0.0.1,而不尝试动态解决它:

    function TIdStack.ResolveHost(const AHost: string;
      const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION): string;
    begin
      Result := '';
      case AIPVersion of
        Id_IPv4: begin
            // Sometimes 95 forgets who localhost is
            if TextIsSame(AHost, 'LOCALHOST') then begin    {Do not Localize}
              Result := '127.0.0.1';    {Do not Localize}
            end else if IsIP(AHost) then begin
              Result := AHost;
            end else begin
              Result := HostByName(AHost, Id_IPv4);
            end;
          end;
        Id_IPv6: begin
            if TextIsSame(AHost, 'LOCALHOST') then begin    {Do not Localize}
              Result := '::1';    {Do not Localize}
            end else begin
              Result := IdGlobal.MakeCanonicalIPv6Address(AHost);
              if Result = '' then begin
                Result := HostByName(AHost, Id_IPv6);
              end;
            end;
          end;
        else begin
          IPVersionUnsupported;
        end;
      end;
    end;
    

    即使 Indy 尝试将 localhost 解析为主机名,它也不会尝试连接到所有报告的 IP。这是 Indy 问题列表中的 TODO item

    我的建议是使用getaddrinfo() 手动解析localhost,然后使用循环遍历报告的IP,重置TIdTCPClient.Host(可能还有TIdTCPClient.IPVersion)并为每个IP调用TIdTCPClient.Connect(),直到一个成功或循环结束。

    【讨论】:

    • 不幸的是,使用 127.0.0.1 给了我同样的问题。此外,在 telnet 上尝试 127.0.0.1 - 也无法正确连接 - 而 localhost 上的 telnet 确实有效。
    • 我知道,这就是我想要表达的观点。当服务器没有主动监听127.0.0.1 时,客户端无法连接到127.0.0.1。将服务器绑定到0.0.0.0 并不能保证绑定到127.0.0.1。客户端必须使用服务器实际侦听的 IP 进行连接。 Indy 仅将localhost 视为127.0.0.1,它不会尝试将localhost 解析为其他本地IP。
    • 很好 - 从来不知道。生病测试这个很快。另一种可能更直接的解决方案是明确告诉 Ruby 从 127.0.0.1 -> server = TCPServer.open("127.0.0.1", 2196)
    • 你可以,但要知道这样做,服务器只能被同一台机器上的客户端访问,不能被同一局域网或其他网络上的外部客户端访问。如果您需要,请将服务器保持原样,让同一台机器上的本地客户端连接到正确的 IP,您可以从 netstat 获得该 IP。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 2013-02-10
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    相关资源
    最近更新 更多