2015-07-26 28 views
6

Say zacznę serwer tak:Jak uzyskać adres http.ListenAndServe

srv := http.Server{ 
    Addr: ":0", 
    Handler: http.FileServer(http.Dir(".")), 
} 
go srv.ListenAndServe() 
log.Printf("Listening on ???") 

Jak mogę sprawdzić, który port został wybrany? :0 jest przeznaczony do wybierania losowego portu efemerycznego przez system operacyjny, ale muszę wiedzieć, który został wybrany.

UWAGA: wolałbym nie stworzyć własną słuchacza i używać srv.Listen(ln), ponieważ srv.ListenAndServe() ma dobrą domyślną (ale unexported) słuchacza, który chcę użyć.

Odpowiedz

2

wolałbym aby nie tworzyć własną słuchacza i używać srv.Listen (LN), ponieważ srv.ListenAndServe() ma dobrą domyślną (ale unexported) słuchacza, który chcę użyć.

Dlaczego nie? ListenAndServe() jest niezwykle prosty w implementacji. Można read the source code za to sam:

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

Odpowiedzią jest to, że trzeba będzie użyć napisać własny ListenAndServe(), która daje informacje, które chcesz. Jest to znacznie łatwiejsze niż myślisz. Cała sprawa nie jest większa niż 20 linii (zakładając, że chcesz ustawić podtrzymywanie przy pomocy tcpKeepAliveListener).

+0

Moje preferencje to tylko preferencja, jestem świadoma tego, że nie jest trudno przejść 'srv.Listen()' trasą. Zakładam, że ponieważ unikasz problemu, nie możesz również znaleźć sposobu na uzyskanie numeru portu? – chowey

+2

Prawidłowo nie można tego zrobić bez rzeczy dużo gorszych niż stworzenie własnego słuchacza. ListenAndServe ma być funkcją wygody. Podobnie jak w przypadku większości takich funkcji, gdy potrzebujesz czegoś specjalnego, musisz użyć funkcji niższego poziomu. –

+3

Należy zauważyć, że używa to nieodportowanego 'tcpKeepAliveListener', więc jeśli chcesz utrzymywać TCP, musisz również [skopiować to źródło] (https://golang.org/src/net/http/server.go?s= 51082: 51123 # L1967) na szczęście to tylko kilkanaście linii trywialnego kodu, ale robi to trochę bardziej denerwujące. –

0

Możesz wybrać wolny port przed skonfigurowaniem adresu serwera. Prostszym sposobem na uzyskanie wolnego portu jest utworzenie słuchacza, dzięki czemu można uzyskać ten sam wynik po sugestii Stephena.

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 
} 

Oto kompletny przykład https://play.golang.org/p/bG4OpmQbz9s

+0

Co się stanie, jeśli system operacyjny przypisze ten port do innego procesu w międzyczasie? – chowey

+0

W takim przypadku wystąpi błąd podczas uruchamiania serwera, należy więc sprawdzić, czy wystąpił błąd i powtórzyć operację. Wybierz inny port, wywołując ponownie metodę GetFreePort i zrestartuj serwer. –