Код
Для воспроизведения требуется два запущенных приложения и соединяющихся друг с другом через TCP. Итак, я сделал крошечное репо, которое также включает скрипт сборки powershell. ссылка на полное репо
Однако, чтобы избежать лишнего клика, вот код для 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)
Проблема
Я строю один и тот же код go для Windows и Linux, но во время выполнения приложения дают разные результаты. В частности, как набираются 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
, поскольку эти два приложения работают в одной среде, поэтому брандмауэры не действуют, а разрешения одинаковы.
Как получить один и тот же результат независимо от платформы? Или почему они отличаются в первую очередь?
Edit
Успешное соединение на Windows - это не просто удача хорошего времени. На Windows я могу запустить A в течение 5 минут, затем при запуске B оба успешно подключатся.
Обновление (2020-04-27)
После получения отзыва от Go разработчики, мне сказали, что это, скорее всего, проблема конфигурации Linux, а не спецификация c до Go. Кроме разрешений, я не могу ничего сказать, что помешало бы двум приложениям в одной среде установить TCP-соединение, подобное этому? (Эти вещи низкого уровня Linux на самом деле не моя сильная сторона.)