英文:
How to get address for http.ListenAndServe
问题
假设我这样启动一个服务器:
srv := http.Server{
Addr: ":0",
Handler: http.FileServer(http.Dir(".")),
}
go srv.ListenAndServe()
log.Printf("Listening on ???")
我如何知道选择了哪个端口?:0
是由操作系统设计的,用于选择一个随机的临时端口,但我需要知道选择了哪个端口。
注意: 我更倾向于不创建自己的监听器并使用 srv.Listen(ln)
,因为 srv.ListenAndServe()
有一个很好的默认(但未公开)监听器,我想要使用它。
英文:
Say I start a server like so:
srv := http.Server{
Addr: ":0",
Handler: http.FileServer(http.Dir(".")),
}
go srv.ListenAndServe()
log.Printf("Listening on ???")
How can I tell which port was picked? :0
is designed to pick a random ephemeral port by the OS, but I need to know which one was picked.
NOTE: I would prefer not to create my own listener and use srv.Listen(ln)
, since srv.ListenAndServe()
has a good default (but unexported) listener that I want to use.
答案1
得分: 2
我宁愿不创建自己的监听器并使用srv.Listen(ln),因为srv.ListenAndServe()有一个很好的默认监听器(但未公开),我想使用它。
为什么不呢?自己实现ListenAndServe()非常简单。你可以自己阅读它的源代码:
func (srv *Server) ListenAndServe() error {
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}
答案是你需要自己编写自己的ListenAndServe()来获取你想要的信息。然而,这比你想象的要容易得多。整个代码不超过20行(假设你想使用tcpKeepAliveListener来设置保持活动连接)。
英文:
> I would prefer not to create my own listener and use srv.Listen(ln), since srv.ListenAndServe() has a good default (but unexported) listener that I want to use.
Why not? ListenAndServe() is extremely simple to implement yourself. You can read the source code for it yourself:
func (srv *Server) ListenAndServe() error {
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}
The answer is that you will need to use write your own ListenAndServe() that gives you the information you want. It is much easier than you believe however. The entire thing isn't more than 20 lines (assuming you want to set keep-alives with tcpKeepAliveListener).
答案2
得分: 2
在配置服务器地址之前,您可以选择一个空闲端口。获取一个空闲端口的简单方法是创建一个监听器,这样您就可以按照Stephen的建议获得相同的结果。
func GetFreePort() (int, error) {
ln, err := net.Listen("tcp", ":0")
if err != nil {
return 0, err
}
err = ln.Close()
if err != nil {
return 0, err
}
return ln.Addr().(*net.TCPAddr).Port, nil
}
这里有一个完整的示例:https://play.golang.org/p/bG4OpmQbz9s
英文:
You can select a free port before configuring the server address. The simpler way to get a free port is to create a listener, so you can obtain the same result following Stephen suggestion.
func GetFreePort() (int, error) {
ln, err := net.Listen("tcp", ":0")
if err != nil {
return 0, err
}
err = ln.Close()
if err != nil {
return 0, err
}
return ln.Addr().(*net.TCPAddr).Port, nil
}
Here a complete example https://play.golang.org/p/bG4OpmQbz9s
答案3
得分: 2
从Go 1.14.1开始,net/http
不再包装TCP监听器!
查看源代码,现在是这样的:
func (srv *Server) ListenAndServe() error {
if srv.shuttingDown() {
return ErrServerClosed
}
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(ln)
}
这是由于这个提交,其中监听器的"keepalive"部分被移动到标准的net
包中,并且现在默认开启。
所以,不用担心!只需创建自己的监听器。
示例
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return err
}
go srv.Serve(ln)
log.Printf("Listening on %s", ln.Addr().String())
英文:
As of Go 1.14.1, net/http
no longer wraps the TCP listener!
Looking at the source code, it is now:
func (srv *Server) ListenAndServe() error {
if srv.shuttingDown() {
return ErrServerClosed
}
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(ln)
}
This is due to this commit, where the "keepalive" part of the listener was moved to the standard net
package and is now turned on by default.
So, don't worry about it! Just create your own listener.
Example
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return err
}
go srv.Serve(ln)
log.Printf("Listening on %s", ln.Addr().String())
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论