【发布时间】:2020-08-10 13:47:32
【问题描述】:
代码
要重现需要两个应用程序运行并通过 TCP 相互连接。所以我做了一个很小的 repo,其中还包括 powershell 构建脚本。 link to the full repo
但是为了避免额外的点击,这里是clientA.go的代码。
package main
import (
"fmt"
"net"
"time"
)
func main() {
clientA, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf(":%v", "2222"))
if err != nil {
fmt.Println(err)
return
}
clientB, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf(":%v", "3333"))
if err != nil {
fmt.Println(err)
return
}
for {
clientAtoB, err := net.DialTCP("tcp4", clientA, clientB)
if err != nil {
fmt.Println(err)
} else {
defer clientAtoB.Close()
clientAtoB.SetLinger(0)
clientAtoB.SetNoDelay(true)
clientAtoB.SetKeepAlive(false)
fmt.Println("connected as Client A!")
buffer := make([]byte, 64)
_, err = clientAtoB.Read(buffer)
if err != nil {
continue
}
}
time.Sleep(time.Second)
}
}
clientB.go 的代码是相同的,只是本地和远程端点交换了:
clientBtoA, err := net.DialTCP("tcp4", clientB, clientA)
问题
我为 Windows 和 Linux 构建了相同的 go 代码,但在运行时应用程序会产生不同的结果。特别是在每个平台上如何拨打 TCP 连接。
在 Windows 上,当我运行两个可执行文件 clientA.exe 和 clientB.exe(由 build.ps1 脚本构建)时,我得到了想要的结果。如此屏幕截图所示:
但是,当我上传并执行 Linux 二进制文件时,结果却有所不同:
ubuntu@ip-172-31-16-224:~/go/src/github.com/fanmanpro/dial-vs-listen$ sudo chmod +x clientA clientB
ubuntu@ip-172-31-16-224:~/go/src/github.com/fanmanpro/dial-vs-listen$ ls -la
total 10984
drwxrwxr-x 3 ubuntu ubuntu 4096 Apr 27 03:09 .
drwxrwxr-x 4 ubuntu ubuntu 4096 Apr 27 03:08 ..
drwxrwxr-x 8 ubuntu ubuntu 4096 Apr 27 03:08 .git
-rw-rw-r-- 1 ubuntu ubuntu 11255 Apr 27 03:12 A.txt
-rw-rw-r-- 1 ubuntu ubuntu 11255 Apr 27 03:12 B.txt
-rw-rw-r-- 1 ubuntu ubuntu 247 Apr 27 03:08 build.ps1
-rwxrwxr-x 1 ubuntu ubuntu 2950662 Apr 27 03:08 clientA
-rw-rw-r-- 1 ubuntu ubuntu 2642944 Apr 27 03:08 clientA.exe
-rw-rw-r-- 1 ubuntu ubuntu 718 Apr 27 03:08 clientA.go
-rwxrwxr-x 1 ubuntu ubuntu 2950662 Apr 27 03:08 clientB
-rw-rw-r-- 1 ubuntu ubuntu 2642944 Apr 27 03:08 clientB.exe
-rw-rw-r-- 1 ubuntu ubuntu 718 Apr 27 03:08 clientB.go
ubuntu@ip-172-31-16-224:~/go/src/github.com/fanmanpro/dial-vs-listen$ ./clientA > A.txt & ./clientB > B.txt &
[1] 24914
[2] 24915
ubuntu@ip-172-31-16-224:~/go/src/github.com/fanmanpro/dial-vs-listen$ cat A.txt
dial tcp4 :2222->:3333: connect: connection refused
ubuntu@ip-172-31-16-224:~/go/src/github.com/fanmanpro/dial-vs-listen$ cat B.txt
dial tcp4 :3333->:2222: connect: connection refused
ubuntu@ip-172-31-16-224:~/go/src/github.com/fanmanpro/dial-vs-listen$
我不希望出现connection refused 错误,因为这两个应用程序在同一环境下运行,因此没有防火墙生效,并且权限相同。
无论平台如何,我怎样才能获得相同的结果?或者为什么它们一开始就不同?
编辑
Windows 上的成功连接不仅仅是时机的运气。在 Windows 上,我可以运行 A 5 分钟,然后当我运行 B 时,都连接成功。
更新(2020-04-27)
在收到 Go 开发人员的反馈后,我被告知这可能是 Linux 配置问题,而不是 Go 特有的问题。除了权限之外,我无法阻止同一环境中的两个应用程序建立这样的 TCP 连接? (这些低级 Linux 的东西并不是我的强项。)
【问题讨论】:
-
我不明白它是怎么工作的这里。即使使用无限重试 for 循环,也不确定事情是否会神奇地正确排列,从而发生连接。这段代码纯靠运气,这是不正确的。
-
@mh-cbon 在 Windows 上,我可以运行 A 5 分钟,然后当我运行 B 时,它连接成功。
-
难以置信。在这两个平台上,您都应该收到一系列“连接被拒绝”消息,直到服务器端启动,然后才成功。根据您发布的代码,没有理由只收到一条此类消息然后退出该过程。