【发布时间】: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_REUSEADDR和SO_REUSEPORT套接字选项。需要注意的是,这些选项不是标准化的。从他们的描述来看,它们似乎用于一些负载非常密集的情况,我想知道 go 例程是否可以缓解它们正在解决的一些问题。 -
Steffen Ullrich 提出的方法在任何情况下都不适用于 TCP,原因我已经说过了。 @MomchilAtanasov