我想根据某种状态来控制一个监听器,假设我的程序将在文件内容为1时监听,而在内容为0时不监听。
问题在于,一旦初始化了侦听器,就无法告诉他拒绝连接。只有“接受”状态;我必须关闭监听器。
所以我找到了一种使用以下代码的方法,但是我觉得这不是一个好方法,因为我使用的是全局变量,通常这不是一个好主意。
有更好的方法吗?
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)
}
}
编辑 : 带通道
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)
}
}
分析解答
健康状况恶化时,请关闭侦听器。使用通道向accept循环发信号,这是完全关闭。
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)
}
接受函数是:
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)
}
}