如何在没有侦听器的情况下创建 TCP 连接?

How do you create a TCP connection without a listener?

我目前正在使用 Winsock 2 开发一个 C++ 网络程序,它是一个在两台计算机之间没有服务器的聊天程序。如果 none 的用户被迫 运行 具有侦听器的服务器程序,这将很方便,这使他们必须转发端口。当然,这会要求他们都输入彼此的 IP,但这没关系。有没有一种方法可以通过 运行 在两台不同的计算机上使用相同的客户端程序,使用相同的端口并且每台输入另一台计算机的 IP 而无需端口转发来创建 TCP 连接?

如果我对你的任务理解正确的话:(2 台不同网络中的家用电脑,没有 "white" ip 地址;通过供应商连接到互联网的电脑)。

答:不能。 你也不能通过 UDP。

你需要一些有 ip 地址的东西,可以从外部网络获得。即具有 "white" ip 地址的命名服务器(或家用计算机)。 "something" 应该会收到您的 TCP 连接。

在TCP中,一方必须调用bind()listen()accept(),而另一方必须调用connect()。没有办法解决这个问题,这就是 TCP 的工作原理。

如果侦听器位于 NAT/Proxy 之后,则必须根据需要使用端口转发。

让客户决定谁最初是监听者,谁是连接者。如果连接失败,请反转角色并重试。如果连接仍然失败,那么您需要一个两个客户端都可以连接到的外部服务器,以促进它们之间的通信。

虽然您需要调用 bind 以允许另一台机器连接到该端口,但您不需要调用 accept.

只要两个进程都在它们的接受端口上调用了bind,那么假设地址sin被初始化为适当的目的地,每个进程就可以使用循环对称地相互连接看起来像这样:

  while (connect(s, sin, slen) < 0) {
      if (errno == ECONNREFUSED) continue;
      perror("connect");
      _exit(0);
  }

这是TCP状态机图中的"simultaneous open"情况。每一方同时发送 SYN,因此每一方都以 SYN/ACK 响应。双方都发送ACK完成3次握手后,双方进入ESTABLISHED状态。

Try It Online不支持线程或访问环回,但它确实允许我方便地展示完整的编码示例。