猿问

GO:为什么从客户端侦听的地址拨号不起作用,而相反呢?

我想知道为什么从客户端也在侦听的地址拨号不起作用(Version A)但侦听客户端拨号到服务器的连接地址实际上有效(Version B)?!


谁可以给我解释一下这个。Go对我来说是新的,我仍然在学习很多东西。


下面是一个例子:


服务器程序:


package main


import . "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 main


import "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 main


import "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())

}


江户川乱折腾
浏览 182回答 1
1回答

侃侃尔雅

“版本 B”作为 Go 的 POSIX 默认设置的副作用,即使它被现有连接使用SO_REUSEADDR,它也允许绑定到一addr:port对。可以区分这 2 个套接字,因为已建立的连接由 的 4 元组标识(LocalAddr, LocalPort, RemoteAddr, RemotePort)。“版本 A”不起作用,因为在设置连接时它需要调用bind以设置请求的本地地址,并且已经有一个绑定到该端口的侦听套接字。没有必要尝试利用这个漏洞,您应该为客户端和服务器连接使用 2 个端口。
随时随地看视频慕课网APP

相关分类

Go
我要回答