I want to control a listener depending on the state of something, let's say my program will listen if the content of a file is 1 and don't listen if the content is 0.
The problem is that there's not way, once a listener is initialized, to tell him to refuse connection. There is only the 'accept' state; I have to close the listener.
So I found a way to do it using the following code, but I feel that's not a good way to do because i'm using a global and usually it's not a good idea.
Is there a better way to do it?
var healthStatus bool
func listen(l net.Listener, port int) {
var err error
l, err = net.Listen("tcp", ":"+strconv.Itoa(port))
if err != nil {
panic(err)
}
defer l.Close()
for {
if healthStatus == false {
_ = l.Close()
return
}
logrus.Debug("Going to listen !")
conn, err := l.Accept()
if err != nil {
panic(err)
}
go func(c net.Conn) {
_ = c.Close()
}(conn)
}
}
func main() {
healthStatus = true
var listener net.Listener
var isListening = false
for {
logrus.Debug("Performing checks...")
healthStatus = healthcheck()
if healthStatus {
if !isListening {
isListening = true
//Restart listener
go listen(listener, config.port)
}
}
if !healthStatus {
if isListening {
isListening = false
}
}
time.Sleep(time.Second * 10)
}
}
EDIT: With channel
package main
import (
"net"
"strconv"
"time"
)
var listening = make(chan bool)
func listen(l net.Listener, port int) {
var err error
l, err = net.Listen("tcp", ":"+strconv.Itoa(port))
if err != nil {
panic(err)
}
defer l.Close()
for {
localstatus := <- listening
if localstatus == false {
_ = l.Close()
return
}
conn, _ := l.Accept()
go func(c net.Conn) {
// Shut down the connection.
_ = c.Close()
listening <- true
}(conn)
}
}
func main() {
healthStatus := true
var listener net.Listener
var isListening = false
for {
healthStatus = healthcheck()
if healthStatus {
if !isListening {
isListening = true
//Restart listener
go listen(listener, config.port)
}
listening <- true
}
if !healthStatus {
if isListening {
isListening = false
listening <- false
}
}
time.Sleep(time.Second * 10)
}
}
Close the listener when the health goes bad. Use a channel to signal the accept loop that it's a clean shutdown.
var listener net.Listener
var done chan struct{}
for {
if healthcheck() {
if listener == nil {
var err error
listener, err = net.Listen("tcp", ":"+strconv.Itoa(conig.port))
if err != nil {
panic(err)
}
done = make(chan struct{})
go accept(listener, done)
}
} else {
if listener != nil {
close(done)
listener.Close()
done = nil
listener = nil
}
}
time.Sleep(time.Second * 10)
}
The accept function is:
func accept(l net.Listener, done chan struct{}) {
for {
conn, err := l.Accept()
select {
case <-done:
return
default:
}
if err != nil {
panic(err)
}
go func(c net.Conn) {
_ = c.Close()
}(conn)
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.