即使端口上没有运行任何东西,绑定地址已经在使用的golang错误

时间:2015-04-28 16:27:42

标签: tcp go port httpserver

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

计划的输出:

..
..
58479个
..
..
58867个
58868个
58869个
..
很好! 58867个
很好! 58868个
很好! 58869个
..
..
..
2015/04/28 09:05:09绑定端口时出错:listen tcp:58479:bind:地址已在使用中

我确保检查出来的免费端口从未重复过。

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)
            }()
    }
}

2 个答案:

答案 0 :(得分:6)

你所做的是检查端口是否在某一点是免费的,然后你尝试使用它,这是基于它过去是免费的。这不会起作用。

会发生什么:在for循环的每次迭代中,您都会生成一个端口号,并确保它是免费的。然后,您生成一个例程,意图使用此端口(已经释放回可用端口池)。你不知道什么时候开始运行。它可能会在主程序(for循环)刚刚生成另一个自由端口时被激活 - 也许是同一个自由端口?或者也许另一个进程同时采用了这个端口。基本上你可以在一个端口上拥有竞争条件。

经过多次研究后发现:

但有一点需要注意。只要本地+远程对是唯一的,两个不同的套接字就可以绑定到同一个ip +端口。我曾经写过一篇关于它的response。因此,当我用:0创建听众时,我能够得到一个"碰撞&#34 ;;由netstat -an证实:

10.0.1.11.65245        *.*                    LISTEN
10.0.1.11.65245        17.143.164.101.5223    ESTABLISHED

现在,问题是如果要显式绑定套接字正在使用的端口,这是不可能的。可能是因为您只能指定本地地址,并且在调用listen或connect之前不会知道远程地址(我们现在谈的是系统调用,而不是Go界面)。换句话说,当您未指定端口时,OS有更广泛的选择。因此,如果它发生了一个也被另一个套接字使用的本地地址,你就无法手动绑定它。

如何解决它:

正如我在评论中提到的那样,您的服务器进程应使用:0表示法,以便能够从操作系统中选择可用资源。一旦它正在倾听,地址应该通知感兴趣的进程。例如,您可以通过文件或标准输出来执行此操作。

答案 1 :(得分:-1)

可能您之前在此端口上运行或调试了一个应用程序,并且它没有完全关闭。该进程可能仍在您的系统内存中。完全终止该进程,以及可能潜伏在阴影中的任何其他网络守护进程,然后再次尝试运行您的应用程序。

如果您还没有检查过,您可以使用(如果使用 Linux)dotnet publishtop 或任何 GUI 系统监视器,例如 Windows 的 htop、Gnome3 的 {{ 1}} 或 KDE 的 Task Manager 来搜索违规进程。

例如,我观察到 Visual Studio Code 的调试器/运行器实用程序 (F5/Ctrl+F5) 并不总是清理进程,尤其是当您按 F5 太快并且旧的调试器没有关闭时。< /p>