关于套接字的 SO_REUSEADDR 不能在 golang 中正常工作吗?

单个 IP 只能支持 65535 端口到单个目标。希望client在性能测试的时候能够立即重用旧的tcp_session,即使session还处于time_wait状态。


在我的 Linux 机器上,我打开了这些开关


sysctl -w net.ipv4.tcp_timestamps=1

sysctl -w net.ipv4.tcp_tw_recycle=1

sysctl -w net.ipv4.tcp_tw_reuse=1

然后我写了下面的代码来用golang验证socket_reuse选项。在代码中,我绑定了本地端口12345。


先跑后


$go run 1.go


$netstat -nat | grep 12345

tcp        0      0 192.168.1.11:12345         111.161.3.173:80            TIME_WAIT

二次运行后


$go run 1.go

Client Connect() called error: cannot assign requested address

似乎 SO_REUSEADDR 不能工作。任何人都可以帮助解决这个问题吗?


package main


import (

    "fmt"

    . "syscall"

)


func main() {

    var (

        clientsock int

        serveraddr SockaddrInet4

        err        error

    )


    if clientsock, err = Socket(AF_INET, SOCK_STREAM, IPPROTO_IP); err != nil {

        fmt.Println("Client Socket() called error:", err.Error())

        return

    }

    SetsockoptInt(clientsock, SOL_SOCKET, SO_REUSEADDR, 1)


    defer Shutdown(clientsock, SHUT_RDWR)


    serveraddr.Addr = [4]byte{111, 161, 3, 173}

    serveraddr.Port = 80


    err = Bind(clientsock, &SockaddrInet4{

        Port: 12345,

    })


    if err = Connect(clientsock, &serveraddr); err != nil {

        fmt.Println("Client Connect() called error:", err.Error())

        return

   }

}


九州编程
浏览 112回答 1
1回答

慕田峪9158850

您应该对代码添加两个更改:1) 设置套接字选项 unix.SO_REUSEPORT。if errReusePort := SetsockoptInt(clientsock, SOL_SOCKET, unix.SO_REUSEPORT, 1); errReusePort != nil {    fmt.Printf("reuse port error: %v\n", errReusePort)    return}2) 使您的代码连接到不同的远程 TCP 端点。否则,由于单一源地址/端口,TCP 将无法区分两个相同的连接(协议、src-addr、src-port、dst-addr、dst-port)。下面的示例在命令行中指定了两个远程服务器地址。$ go run main.go 127.0.0.1connected$ go run main.go 127.0.0.2connected在操场上找到完整的工作代码:https ://play.golang.org/p/HYLkWlVH6T4
打开App,查看更多内容
随时随地看视频慕课网APP