如何重用已拨号的TCP端口

huangapple go评论90阅读模式
英文:

how to reuse a dialed tcp port

问题

简化一下:

有一个服务器(192.168.0.78)在8013端口上监听。
一个客户端(10.0.2.15)尝试连接服务器,并获取其本地端口(例如54591)。

如何使客户端关闭连接并重用54591端口?
我尝试了以下方法:

  1. 直接关闭连接并监听相同的端口:无法重用端口。
  2. 启动另一个程序(B)连接服务器并退出,然后尝试监听程序B使用的端口:端口未知。

有没有正确的方法来做到这一点?
代码很简单:

客户端:

func main() {
    conn, err := net.Dial("tcp", "192.168.0.78:8013")
    if err != nil {
        panic(err)
    }
    localAddr := conn.LocalAddr().String()
    conn.Close()
    // 我得到了本地端口,接下来该怎么做?
    fmt.Println(localAddr)
}

服务器:

func main() {
    ln, err := net.Listen("tcp", ":8013")
    if err != nil {
        panic(err)
    }
    for i := 0; i < 5; i++ {
        conn, err := ln.Accept()
        if err != nil {
            panic(err)
        }
        fmt.Println(conn.RemoteAddr().String(), "connected")
        conn.Close()
    }
}
英文:

making it short:<br>
a server(192.168.0.78) listens on 8013<br>
a client(10.0.2.15) tries to connect the server, getting its local port(eg.54591)

how to make the client close the connection and reuse 54591?<br>
i tried and got:<br>

  1. close the connection directly and listen the same port:<b>can not reuse port</b><br>
  2. launch another program(B) to connect server and exit, then tried to listen the port B has used:<b>unknown port</b><br>

is there a correct way to do this?<br>
code is simple:<br>
client<br>

func main() {                                                                                                                    
    conn, err := net.Dial(&quot;tcp&quot; , &quot;192.168.0.78:8013&quot;)                                                                           
    if err != nil {                                                                                                              
        panic(err)                                                                                                               
    }                                                                                                                            
    localAddr := conn.LocalAddr().String()                                                                                       
    conn.Close()                                                                                                                 
    // i got the local port, what to do?                                                                                         
    fmt.Println(localAddr)                                                                                                       
}      

server<br>

func main(){                                                                                                                     
    ln, err := net.Listen(&quot;tcp&quot;, &quot;:8013&quot;)                                                                                        
    if err != nil {                                                                                                              
        panic(err)                                                                                                               
    }                                                                                                                            
    for i := 0; i &lt; 5; i++ {                                                                                                     
        conn, err := ln.Accept()                                                                                                 
        if err != nil {                                                                                                          
            panic(err)                                                                                                           
        }                                                                                                                        
        fmt.Println(conn.RemoteAddr().String(), &quot;connected&quot;)                                                                     
        conn.Close()                                                                                                             
    }                                                                                                                            
}  

答案1

得分: 1

如果你想让客户端使用特定的本地端口号,你必须在create()之后但在connect()之前进行bind()操作。你可以使用bind函数指定任何本地端口号(和/或特定接口)。

要重用以前的端口号,你必须将该端口号通知给下一次连接尝试,并且每次都要使用SO_REUSEADDR("reuse"选项)打开它,否则第二次绑定将不被允许,直到第一个绑定完全过期(通常是在关闭后的2分钟内)。

这些是C函数名。Go语言会有类似的功能。

英文:

If you want a client to use a specific local port number, you must bind() after you create() but before you connect(). You can specify any local port number (and/or specific interface) with bind.

To reuse a previous port number, you have to make that port number known to the next connection attempt and you must open it with the SO_REUSEADDR "reuse" option each time or the second bind will not be allowed until the first one fully expires (often 2 minutes after it was closed).

Those are C function names. Go will have something similar.

答案2

得分: 0

这是Go语言net包的一个已知问题。

有几种解决方法,比如这个包:https://github.com/jbenet/go-reuseport

英文:

This is a known problem of Go's net package.

There are couple of workarounds, like this package, for instance: https://github.com/jbenet/go-reuseport

huangapple
  • 本文由 发表于 2015年11月5日 17:03:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/33540302.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定