I am playing with go lately and trying to make some server which responds to clients on a tcp connection.
My question is how do i cleanly shutdown the server and interrupt the go-routine which is currently "blocked" in the following call
func (*TCPListener) Accept?
According to the documentation of Accept
Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.
The errors are also very scarcely documented.
Here is what i was looking for. Maybe helps someone in the future. Notice the use of select and the "c" channel to combine it with the exit channel
ln, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
defer ln.Close()
for {
type accepted struct {
conn net.Conn
err error
}
c := make(chan accepted, 1)
go func() {
conn, err := ln.Accept()
c <- accepted{conn, err}
}()
select {
case a := <-c:
if a.err != nil {
// handle error
continue
}
go handleConnection(a.conn)
case e := <-ev:
// handle event
return
}
}
Simply Close()
the net.Listener
you get from the net.Listen(...)
call and return from the executing goroutine.
You don't necessarily need an extra go routine (that keeps accepting), simply specify a Deadline
.
for
example:
for {
// Check if someone wants to interrupt accepting
select {
case <- someoneWantsToEndMe:
return // runs into "defer listener.Close()"
default: // nothing to do
}
// Accept with Deadline
listener.SetDeadline(time.Now().Add(1 * time.Second)
conn, err := listener.Accept()
if err != nil {
// TODO: Could do some err checking (to be sure it is a timeout), but for brevity
continue
}
go handleConnection(conn)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With