【问题标题】:force connect to work强制连接工作
【发布时间】:2012-10-19 00:56:46
【问题描述】:

我在运行 red hat 5 的虚拟机上以 bash 运行以下行:

    for i in {1..100000};
        do telnet 10.10.10.105 41941;
    done

在某些时候,telnet 会连接到端口,即使没有人在监听它。它似乎正在连接到它的自我? 当我启动应用程序的客户端时出现同样的问题,没有启动服务器 - 客户端成功连接到 ip:port。客户端看起来像这样:

    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(port));
    addr.sin_addr.s_addr = inet_addr(hostname);

    some_while_loop
    {
        status = ::connect(sock, (sockaddr *)&addr, sizeof(addr));
        if (status == -1)
        {
            shutdown(sock, 2);
            close(sock);
            return false;
        }
   }

我找到了这篇文章:http://web.deu.edu.tr/doc/soket/,它在 6.2 中指出,如果您连接到正在运行的同一台机器,连接将会成功。我的问题是,为什么会这样?是硬件问题还是正在使用故障安全的红帽内核,或者可能是因为我正在使用的端口(例如,对于 1025,我没有这个问题)...?

【问题讨论】:

    标签: performance unix networking connect telnet


    【解决方案1】:

    它与端口相关。启动 TCP 连接时,对于客户端,会选择端口上限 (32786+) 中随机未使用的端口。然后通常的TCP handshake 就完成了,只有一种称为同时启动的特殊情况。这里假设连接的双方都想同时建立一个连接,见下图来自RFC。

    您可以使用 ncat 强制执行该行为:

    ncat -p 50000 127.0.0.1 50000
    

    这将使 ncat 连接到127.0.0.1:50000,同时使用源端口50000。您可以立即获得有效连接,而无需事先侦听传入连接。


    不管评论者怎么说,这里发生的案例称为同时启动,在RFC 793, Section 3.4中有详细说明,其中写道:

    同时启动只是稍微复杂一些,如图 8 所示。每个 TCP 循环从 CLOSED 到 SYN-SENT 到 SYN-RECEIVED 到 ESTABLISHED。

          TCP A                                            TCP B
    
      1.  CLOSED                                           CLOSED
    
      2.  SYN-SENT     --> <SEQ=100><CTL=SYN>              ...
    
      3.  SYN-RECEIVED <-- <SEQ=300><CTL=SYN>              <-- SYN-SENT
    
      4.               ... <SEQ=100><CTL=SYN>              --> SYN-RECEIVED
    
      5.  SYN-RECEIVED --> <SEQ=100><ACK=301><CTL=SYN,ACK> ...
    
      6.  ESTABLISHED  <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED
    
      7.               ... <SEQ=101><ACK=301><CTL=ACK>     --> ESTABLISHED
    
                    Simultaneous Connection Synchronization
    
                                   Figure 8.
    

    我还更正了第一段,使其更加清晰和准确。

    【讨论】:

    • 嗯,对 SYN 的回复不是 ACK,它是 SYN+ACK,而在连接完成之前,它又必须得到 ACK。我认为这里的底层机制有些不同。
    • @EJP 请查看编辑后的答案并重新考虑否决/删除!
    • @JonasWielicki,同时启动似乎确实如此,因为在连接时,所述地址和端口实际上并没有被阻塞,因此 connect() 将它们视为链接套接字的可行选项。作为解决此问题的方法,我发现您可以getsockname(sock, &amp;sock_addr, &amp;addr_size) 检查端口是否相同,然后关闭连接。同样使用 setsockopt 设置上述套接字以重用地址(SO_REUSEADDR),如果服务器尝试使用相同的地址和端口,将解决任何问题。非常感谢您的帮助
    • 没错。如果端口阻塞,则它们最初不能用于连接。乍一看,这似乎有点自相矛盾。
    猜你喜欢
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 2017-10-25
    • 2020-01-11
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 2015-02-26
    相关资源
    最近更新 更多