【问题标题】:How to connect with TCP to different hosts from the same source ip and port如何使用 TCP 连接来自相同源 ip 和端口的不同主机
【发布时间】:2019-11-23 19:50:32
【问题描述】:

我想在一个进程和已经在监听传入 TCP 连接的其他进程之间启动 TCP 连接。 我想为这些连接使用相同的源地址(ip-port)。 我正在用 Go 编程。

我尝试运行此代码,但第二次 DialTCP 调用失败。

func main() {

    ourAddr, _ := net.ResolveTCPAddr("tcp", "localhost:51234")

    otherAddr1, _ := net.ResolveTCPAddr("tcp", "localhost:51236")
    otherAddr2, _ := net.ResolveTCPAddr("tcp", "localhost:51237")

    conn1, err1 := net.DialTCP("tcp", ourAddr, otherAddr1)
    if err1 != nil {
        log.Fatal("err1: " + err1.Error())
    }
    defer conn1.Close()

    conn2, err2 := net.DialTCP("tcp", ourAddr, otherAddr2) // <- this fails
    if err2 != nil {
        log.Fatal("err2: " + err2.Error())
    }
    defer conn2.Close()

}

错误信息是:err2: dial tcp 127.0.0.1:51234->127.0.0.1:51237: bind: address already in use

(问题应该与目标进程无关,因为 netcat 的两个实例已经在侦听目标地址)

我也尝试使用其他端口(以防它们仍在使用中),但以同样的方式失败

这是我的 go 版本: go version go1.13.4 linux/amd64

在我看来,问题与 TCP 无关,而是与我使用 Go 库的方式有关。 我做错了什么,我该怎么做?

【问题讨论】:

  • 理论上这在 TCP 中应该是可能的,但在实践中是不可能的,因为在 C 级别上,bind()connect() 之前。你不能依赖这种东西。
  • @SteffenUllrich 提出的方法似乎是您正在寻找的。它使用SO_REUSEADDRSO_REUSEPORT 套接字选项。需要注意的是,这些选项不是标准化的。从他们的描述来看,它们似乎用于一些负载非常密集的情况,我想知道 go 例程是否可以缓解它们正在解决的一些问题。
  • Steffen Ullrich 提出的方法在任何情况下都不适用于 TCP,原因我已经说过了。 @MomchilAtanasov

标签: go tcp


【解决方案1】:

您面临的问题是一般问题,与 Go 编程语言无关。

据我所知,您应该无法从相同的源 IP 地址和端口连接到两个目的地。我很确定您收到的消息支持了这一点。

err2: dial tcp 127.0.0.1:51234->127.0.0.1:51237: bind: address already in use

它不是在抱怨您的目的地地址。它抱怨源地址127.0.0.1:51234。尝试更改您的源地址,看看会发生什么。


编辑:似乎有套接字选项 SO_REUSEADDRSO_REUSEPORT 允许这样做,但它们是非标准化的,并且似乎用于验证特定的负载密集型场景。

了解您为什么要实现这样的设置会有所帮助。


补充:有一个stackoverflow问题与你的问题有关:TCP: can two different sockets share a port?

【讨论】:

  • 你描述的交错数据不可能出现。
  • @user207421,需要解释一下吗?我所描述的是一个假设的问题,如果流 API 要从两个流中接收。除了缓冲区大小和 TCP 之外,这在什么方面是不可能的?
猜你喜欢
  • 2018-12-16
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
  • 2016-04-14
  • 2020-12-03
  • 2011-08-08
  • 1970-01-01
  • 2013-09-29
相关资源
最近更新 更多