我想知道為什么從客戶端也在偵聽的地址撥號不起作用(Version A)但偵聽客戶端撥號到服務器的連接地址實際上有效(Version B)?!誰可以給我解釋一下這個。Go對我來說是新的,我仍然在學習很多東西。下面是一個例子:服務器程序:package mainimport . "fmt"import "net"import "os"func main() { Println("server") var listener, listenerError = net.Listen("tcp", "localhost:8080") if listenerError != nil { Println(listenerError) os.Exit(1) } for { con, _ := listener.Accept() // I don't care about the error in this example Printf("LocalAddr: %v\n", con.LocalAddr()) Printf("RemoteAddr: %v\n", con.RemoteAddr()) }}客戶端版本 A(不工作):package mainimport "net"import . "fmt"import "os"func main() { var listener, listenerError = net.Listen("tcp", "localhost:0") if listenerError != nil { Println(listenerError) os.Exit(1) } var dialer = new(net.Dialer) dialer.LocalAddr = listener.Addr() con, err := dialer.Dial("tcp", "localhost:8080") if err != nil { // dial tcp 127.0.0.1:60229->127.0.0.1:8080: bind: address already in use Println(err) os.Exit(2) } Printf("LocalAddr: %v\n", con.LocalAddr()) Printf("RemoteAddr: %v\n", con.RemoteAddr())}客戶端版本 B(工作):package mainimport "net"import . "fmt"import "os"func main() { Println("client") con, err := net.Dial("tcp", "localhost:8080") if err != nil { Println(err) os.Exit(2) } // magic happens here var listener, listenerError = net.Listen("tcp", con.LocalAddr().String()) if listenerError != nil { Println(listenerError) os.Exit(1) } Println("LISTENING") conn, _ := listener.Accept() // will accept on con.LocalAddr() Printf("LocalAddr: %v\n", conn.LocalAddr()) Printf("RemoteAddr: %v\n", conn.RemoteAddr())}
1 回答

侃侃爾雅
TA貢獻1801條經驗 獲得超16個贊
“版本 B”作為 Go 的 POSIX 默認設置的副作用,即使它被現有連接使用SO_REUSEADDR
,它也允許綁定到一addr:port
對。可以區分這 2 個套接字,因為已建立的連接由 的 4 元組標識(LocalAddr, LocalPort, RemoteAddr, RemotePort)
。
“版本 A”不起作用,因為在設置連接時它需要調用bind
以設置請求的本地地址,并且已經有一個綁定到該端口的偵聽套接字。
沒有必要嘗試利用這個漏洞,您應該為客戶端和服務器連接使用 2 個端口。
- 1 回答
- 0 關注
- 208 瀏覽
添加回答
舉報
0/150
提交
取消