How do I stop a Listening server in Go

前端 未结 4 1987
长发绾君心
长发绾君心 2020-12-29 06:09

I\'ve been trying to find a way to stop a listening server in Go gracefully. Because listen.Accept blocks it is necessary to close the listening socket to sign

相关标签:
4条回答
  • 2020-12-29 06:39

    Here's a simple way that's good enough for local development.

    http://www.sergiotapia.me/how-to-stop-your-go-http-server/


    package main
    
    import (  
        "net/http"
        "os"
    
        "github.com/bmizerany/pat"
    )
    
    var mux = pat.New()
    
    func main() {  
        mux.Get("/kill", http.HandlerFunc(kill))
        http.Handle("/", mux)
        http.ListenAndServe(":8080", nil)
    }
    
    func kill(w http.ResponseWriter, r *http.Request) {  
        os.Exit(0)
    }
    
    0 讨论(0)
  • 2020-12-29 06:40

    Something among these lines might work in this case, I hope:

    // Listen for incoming connections
    func (es *EchoServer) serve() {
            for {
                    conn, err := es.listen.Accept()
                    if err != nil {
                        if x, ok := err.(*net.OpError); ok && x.Op == "accept" { // We're done
                                log.Print("Stoping")
                                break
                        }
    
                        log.Printf("Accept failed: %v", err)
                        continue
                    }
                    go es.respond(conn.(*net.TCPConn))
            }
            es.done <- true
    }
    
    0 讨论(0)
  • 2020-12-29 06:53

    I would handle this by using es.done to send a signal before it closes the connection. In addition to the following code you'd need to create es.done with make(chan bool, 1) so that we can put a single value in it without blocking.

    // Listen for incoming connections
    func (es *EchoServer) serve() {
      for {
        conn, err := es.listen.Accept()
        if err != nil {
          select {
          case <-es.done:
            // If we called stop() then there will be a value in es.done, so
            // we'll get here and we can exit without showing the error.
          default:
            log.Printf("Accept failed: %v", err)
          }
          return
        }
        go es.respond(conn.(*net.TCPConn))
      }
    }
    
    // Stop the server by closing the listening listen
    func (es *EchoServer) stop() {
      es.done <- true   // We can advance past this because we gave it buffer of 1
      es.listen.Close() // Now it the Accept will have an error above
    }
    
    0 讨论(0)
  • 2020-12-29 07:01

    Check some "is it time to stop" flag in your loop right after the accept() call, then flip it from your main, then connect to your listening port to get server socket "un-stuck". This is very similar to the old "self-pipe trick".

    0 讨论(0)
提交回复
热议问题