gpt4 book ai didi

tcp - 即使端口上没有任何运行,绑定(bind)地址已在使用中的 golang 错误

转载 作者:IT王子 更新时间:2023-10-29 00:56:14 49 4
gpt4 key购买 nike

我在 golang 中有一个设置,它基本上从操作系统获取一个空闲端口,然后在其上启动一个 http 服务器。它开始出现端口注册失败的随机错误。我将其简化为以下程序,在获取了几个空闲端口后似乎出错了。它非常随机地发生,并且没有真正的进程在它出错的端口上运行。为什么这必须出错对我来说根本没有意义。任何帮助将不胜感激。

程序输出:

..
..
58479
..
..
58867
58868
58869
..
绑定(bind)好! 58867
绑定(bind)好! 58868
绑定(bind)好! 58869
..
..
..
2015/04/28 09:05:09 绑定(bind)端口时出错:listen tcp :58479: bind: address already in use

我确保检查出来的自由端口从未重复。

package main

import (
"net"
"net/http"
"log"
"fmt"
)

func main() {

for {
l, _ := net.Listen("tcp", ":0")
var port = l.Addr().String()[5:]
l.Close()
fmt.Println(port)
go func() {
l1, err := net.Listen("tcp", ":"+port)
if (err != nil) {
log.Fatal("Error while binding port: ", err.Error())
} else {
fmt.Println("bound well! ", port)
}
http.Serve(l1, nil)
}()
}
}

最佳答案

你所做的是检查端口是否在某一时刻空闲,然后根据它过去空闲的事实尝试使用它。这是行不通的。

会发生什么:对于 for 循环的每次迭代,您都会生成一个端口号并确保它是空闲的。然后你生成一个例程以使用这个端口(它已经被释放回空闲端口池)。您真的不知道例程何时启动。它可能在主例程(for 循环)刚刚生成另一个空闲端口时被激活——也许又是同一个?或者也许另一个进程同时占用了这个端口。本质上,您可以在单个端口上设置竞争条件。

经过更多研究:

不过有一个小警告。只要本地+远程对是唯一的,两个不同的套接字就可以绑定(bind)到同一个 ip+端口。我曾经写过 response关于它。因此,当我使用 :0 创建监听器时,我能够得到一个“碰撞”; netstat -an 证明:

10.0.1.11.65245        *.*                    LISTEN
10.0.1.11.65245 17.143.164.101.5223 ESTABLISHED

现在,问题是如果你想显式地将套接字绑定(bind)到正在使用的端口,这是不可能的。可能是因为您只能指定本地地址,而在调用 listen 或 connect 之前不会知道远程地址(我们现在谈论的是系统调用,而不是 Go 接口(interface))。换句话说,当你不指定端口时,操作系统有更广泛的选择。因此,如果发生这种情况,您获得的本地地址也被另一个套接字使用,您将无法手动绑定(bind)到它。

如何解决:

正如我在评论中提到的,您的服务器进程应该使用 :0 符号,以便能够从操作系统中选择可用资源。一旦它开始监听,地址就应该被宣布给感兴趣的进程。例如,您可以通过文件或标准输出来完成。

关于tcp - 即使端口上没有任何运行,绑定(bind)地址已在使用中的 golang 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29924910/

49 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com