强制连接到工作网络

3

我在运行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),我没有遇到这个问题…?
1个回答

0

它与端口相关。在初始化TCP连接时,对于客户端,会选择一个未使用的随机端口(32786+)在端口的上限范围内。然后进行通常的TCP握手,只不过有一种特殊情况叫做同时初始化。在这种情况下,假设连接的两端都想同时建立连接,请参见RFC中的下图。

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

ncat -p 50000 127.0.0.1 50000

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


尽管评论者所说的情况,这里发生的情况被称为同时初始化,并在RFC 793,第3.4节中得到了很好的说明,其中写道:

Simultaneous initiation is only slightly more complex, as is shown in figure 8. Each TCP cycles from CLOSED to SYN-SENT to SYN-RECEIVED to 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。我认为这里的基本机制有些不同。 - user207421
@EJP请查看编辑后的答案并重新考虑取消投票/删除投票! - Jonas Schäfer
@JonasWielicki,同时初始化确实是可能的,因为在连接时,该地址和端口实际上并没有被阻塞,所以connect()将它们视为可行的选项来链接套接字。作为解决方法,我发现您可以使用getsockname(sock, &sock_addr, &addr_size)来检查端口是否相同,并因此关闭连接。此外,使用setsockopt将上述套接字设置为重用地址(SO_REUSEADDR),如果服务器尝试使用相同的地址和端口,则可以解决任何问题。非常感谢您的帮助。 - user1783445
没错。如果端口被阻塞了,它们就不能用于最初的连接。虽然一开始看起来有点自相矛盾。 - Jonas Schäfer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接