mirror of
https://github.com/taigrr/go-fastping
synced 2025-01-18 05:03:15 -08:00
Simplify RunLoop() call and add Stop()
This commit is contained in:
parent
a97a44952e
commit
88c0127fe9
@ -40,20 +40,18 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
p.MaxRTT = time.Second
|
p.MaxRTT = time.Second
|
||||||
quit, errch := p.RunLoop()
|
errch := p.RunLoop()
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
signal.Notify(c, os.Interrupt)
|
signal.Notify(c, os.Interrupt)
|
||||||
signal.Notify(c, syscall.SIGTERM)
|
signal.Notify(c, syscall.SIGTERM)
|
||||||
wait := make(chan bool)
|
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-c:
|
case <-c:
|
||||||
fmt.Println("get interrupted")
|
fmt.Println("get interrupted")
|
||||||
signal.Stop(c)
|
break loop
|
||||||
quit <- wait
|
|
||||||
case res := <-onRecv:
|
case res := <-onRecv:
|
||||||
if _, ok := results[res.addr.String()]; ok {
|
if _, ok := results[res.addr.String()]; ok {
|
||||||
results[res.addr.String()] = res
|
results[res.addr.String()] = res
|
||||||
@ -69,10 +67,9 @@ loop:
|
|||||||
}
|
}
|
||||||
case err := <-errch:
|
case err := <-errch:
|
||||||
fmt.Println("Ping failed: %v", err)
|
fmt.Println("Ping failed: %v", err)
|
||||||
signal.Stop(c)
|
break loop
|
||||||
quit <- wait
|
|
||||||
case <-wait:
|
|
||||||
break loop;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
signal.Stop(c)
|
||||||
|
p.Stop()
|
||||||
}
|
}
|
||||||
|
63
fastping.go
63
fastping.go
@ -71,7 +71,9 @@ type Pinger struct {
|
|||||||
id int
|
id int
|
||||||
seq int
|
seq int
|
||||||
// key string is IPAddr.String()
|
// key string is IPAddr.String()
|
||||||
addrs map[string]*net.IPAddr
|
addrs map[string]*net.IPAddr
|
||||||
|
quit chan chan<- bool
|
||||||
|
running bool
|
||||||
// Number of (nano,milli)seconds of an idle timeout. Once it passed,
|
// Number of (nano,milli)seconds of an idle timeout. Once it passed,
|
||||||
// the library calls an idle callback function. It is also used for an
|
// the library calls an idle callback function. It is also used for an
|
||||||
// interval time of RunLoop() method
|
// interval time of RunLoop() method
|
||||||
@ -88,6 +90,7 @@ func NewPinger() *Pinger {
|
|||||||
id: rand.Intn(0xffff),
|
id: rand.Intn(0xffff),
|
||||||
seq: rand.Intn(0xffff),
|
seq: rand.Intn(0xffff),
|
||||||
addrs: make(map[string]*net.IPAddr),
|
addrs: make(map[string]*net.IPAddr),
|
||||||
|
running: false,
|
||||||
MaxRTT: time.Second,
|
MaxRTT: time.Second,
|
||||||
handlers: make(map[string]interface{}),
|
handlers: make(map[string]interface{}),
|
||||||
Debug: false,
|
Debug: false,
|
||||||
@ -152,7 +155,7 @@ func (p *Pinger) AddHandler(event string, handler interface{}) error {
|
|||||||
// an error value. It means it blocks until MaxRTT seconds passed. For the
|
// an error value. It means it blocks until MaxRTT seconds passed. For the
|
||||||
// purpose of sending/receiving packets over and over, use RunLoop().
|
// purpose of sending/receiving packets over and over, use RunLoop().
|
||||||
func (p *Pinger) Run() error {
|
func (p *Pinger) Run() error {
|
||||||
return p.run(true, make(chan chan<- bool))
|
return p.run(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invode send/receive procedure repeatedly. It sends packets to all hosts which
|
// Invode send/receive procedure repeatedly. It sends packets to all hosts which
|
||||||
@ -161,40 +164,42 @@ func (p *Pinger) Run() error {
|
|||||||
// After MaxRTT seconds, it calls "idle" handler, resend packets and wait those
|
// After MaxRTT seconds, it calls "idle" handler, resend packets and wait those
|
||||||
// response. MaxRTT works as an interval time.
|
// response. MaxRTT works as an interval time.
|
||||||
//
|
//
|
||||||
// This is a non-blocking method so immediately returns with channel values.
|
// This is a non-blocking method so immediately returns with channel value.
|
||||||
// If you want to stop sending packets, send a channel value of bool type to it
|
// If you want to stop sending packets, use Stop(). For example,
|
||||||
// and wait for graceful shutdown. For example,
|
|
||||||
//
|
//
|
||||||
// wait := make(chan bool)
|
// errch := p.RunLoop()
|
||||||
// quit, errch := p.RunLoop()
|
|
||||||
// ticker := time.NewTicker(time.Millisecond * 250)
|
// ticker := time.NewTicker(time.Millisecond * 250)
|
||||||
// loop:
|
// select {
|
||||||
// for {
|
// case err := <-errch:
|
||||||
// select {
|
// log.Fatalf("Ping failed: %v", err)
|
||||||
// case err := <-errch:
|
// case <-ticker.C:
|
||||||
// log.Fatalf("Ping failed: %v", err)
|
// break
|
||||||
// case <-ticker.C:
|
|
||||||
// ticker.Stop()
|
|
||||||
// quit <- wait
|
|
||||||
// case <-wait:
|
|
||||||
// break loop
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
|
// ticker.Stop()
|
||||||
|
// p.Stop()
|
||||||
//
|
//
|
||||||
// For more detail, please see "cmd/ping/ping.go".
|
// For more detail, please see "cmd/ping/ping.go".
|
||||||
func (p *Pinger) RunLoop() (chan<- chan<- bool, <-chan error) {
|
func (p *Pinger) RunLoop() <-chan error {
|
||||||
quit := make(chan chan<- bool)
|
p.quit = make(chan chan<- bool)
|
||||||
errch := make(chan error)
|
errch := make(chan error)
|
||||||
go func(ch chan<- error) {
|
go func(ch chan<- error) {
|
||||||
err := p.run(false, quit)
|
err := p.run(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch <- err
|
ch <- err
|
||||||
}
|
}
|
||||||
}(errch)
|
}(errch)
|
||||||
return quit, errch
|
return errch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pinger) run(once bool, quit <-chan chan<- bool) error {
|
func (p *Pinger) Stop() {
|
||||||
|
if p.running {
|
||||||
|
wait := make(chan bool)
|
||||||
|
p.quit <- wait
|
||||||
|
<-wait
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pinger) run(once bool) error {
|
||||||
p.debugln("Run(): Start")
|
p.debugln("Run(): Start")
|
||||||
conn, err := net.ListenIP("ip4:icmp", &net.IPAddr{IP: net.IPv4zero})
|
conn, err := net.ListenIP("ip4:icmp", &net.IPAddr{IP: net.IPv4zero})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -212,14 +217,13 @@ func (p *Pinger) run(once bool, quit <-chan chan<- bool) error {
|
|||||||
queue, err := p.sendICMP4(conn)
|
queue, err := p.sendICMP4(conn)
|
||||||
|
|
||||||
ticker := time.NewTicker(p.MaxRTT)
|
ticker := time.NewTicker(p.MaxRTT)
|
||||||
|
p.running = true
|
||||||
|
|
||||||
mainloop:
|
mainloop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case join = <-quit:
|
case join = <-p.quit:
|
||||||
p.debugln("Run(): <-quit")
|
p.debugln("Run(): <-p.quit")
|
||||||
p.debugln("Run(): stoprecv <- waitjoin")
|
|
||||||
stoprecv <- waitjoin
|
|
||||||
break mainloop
|
break mainloop
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
if handler, ok := p.handlers["idle"]; ok && handler != nil {
|
if handler, ok := p.handlers["idle"]; ok && handler != nil {
|
||||||
@ -228,8 +232,6 @@ mainloop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if once || err != nil {
|
if once || err != nil {
|
||||||
p.debugln("Run(): stoprecv <- waitjoin")
|
|
||||||
stoprecv <- waitjoin
|
|
||||||
break mainloop
|
break mainloop
|
||||||
}
|
}
|
||||||
p.debugln("Run(): call sendICMP4()")
|
p.debugln("Run(): call sendICMP4()")
|
||||||
@ -240,8 +242,11 @@ mainloop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.running = false
|
||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
|
|
||||||
|
p.debugln("Run(): stoprecv <- waitjoin")
|
||||||
|
stoprecv <- waitjoin
|
||||||
p.debugln("Run(): <-waitjoin")
|
p.debugln("Run(): <-waitjoin")
|
||||||
<-waitjoin
|
<-waitjoin
|
||||||
if !once {
|
if !once {
|
||||||
|
@ -199,21 +199,16 @@ func TestRunLoop(t *testing.T) {
|
|||||||
t.Fatalf("Failed to add idle handler: %v", err)
|
t.Fatalf("Failed to add idle handler: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wait := make(chan bool)
|
errch := p.RunLoop()
|
||||||
quit, errch := p.RunLoop()
|
|
||||||
ticker := time.NewTicker(time.Millisecond * 250)
|
ticker := time.NewTicker(time.Millisecond * 250)
|
||||||
loop:
|
select {
|
||||||
for {
|
case err := <-errch:
|
||||||
select {
|
t.Fatalf("Pinger returns error %v", err)
|
||||||
case err := <-errch:
|
case <-ticker.C:
|
||||||
t.Fatalf("Pinger returns error %v", err)
|
break
|
||||||
case <-ticker.C:
|
|
||||||
ticker.Stop()
|
|
||||||
quit <- wait
|
|
||||||
case <-wait:
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ticker.Stop()
|
||||||
|
p.Stop()
|
||||||
|
|
||||||
if recvCount < 2 {
|
if recvCount < 2 {
|
||||||
t.Fatalf("Pinger receive count less than 2")
|
t.Fatalf("Pinger receive count less than 2")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user