func (this *Pinger) Stop() {
	this.stopOnce.Do(func() {
		this.quit()
		this.rconn.Close()
		this.pconn.Close()
		this.wg.Wait()
		this.done = nil
		this.reschan = nil
		atomic.CompareAndSwapInt64(&this.pid, this.pid, 0)
	})
}
Stop stops the pinging processes.
package netx
import (
	"bytes"
	"encoding/binary"
	"encoding/gob"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"runtime"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
	"github.com/surgebase/glog"
	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
	"golang.org/x/net/ipv6"
)
const (
	icmpHeaderSize   = 8
	defaultInterval  = 100 * time.Millisecond
	defaultMaxRTT    = 100 * time.Millisecond
	defaultTTL       = 32
	defaultSize      = 8
	ProtocolICMP     = 1
	ProtocolIPv6ICMP = 58
)
func Ping(ip string) (*PingResult, error) {
	pinger := &Pinger{}
	pinger.AddIPs([]string{ip})
	res, err := pinger.Start()
	if err != nil {
		return nil, err
	}
	select {
	case pr := <-res:
		return pr, nil
	case <-time.Tick(100 * time.Millisecond):
		return nil, fmt.Errorf("ping/Ping: timed out waiting for echo reply")
	}
}
type PingResult struct {
	Src net.IP
	Dst net.IP
	TOS int
	TTL int
	Type icmp.Type
	Code int
	ID int
	Seq int
	Size int
	RTT time.Duration
	Err error
}
func (this *PingResult) GobDecode(p []byte) error {
	buf := bytes.NewBuffer(p)
	dec := gob.NewDecoder(buf)
	if err := dec.Decode(&this.Src); err != nil {
		return err
	}
	if err := dec.Decode(&this.Dst); err != nil {
		return err
	}
	if err := dec.Decode(&this.TOS); err != nil {
		return err
	}
	if err := dec.Decode(&this.TTL); err != nil {
		return err
	}
	if err := dec.Decode(&this.Code); err != nil {
		return err
	}
	if err := dec.Decode(&this.ID); err != nil {
		return err
	}
	if err := dec.Decode(&this.Seq); err != nil {
		return err
	}
	if err := dec.Decode(&this.Size); err != nil {
		return err
	}
	if err := dec.Decode(&this.RTT); err != nil {
		return err
	}
	var errstr string
	if err := dec.Decode(&errstr); err != nil && err != io.EOF {
		return err
	} else if err != io.EOF {
		this.Err = errors.New(errstr)
	}
	return nil
}
func (this PingResult) GobEncode() ([]byte, error) {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	if err := enc.Encode(this.Src); err != nil {
		return nil, err
	}
	if err := enc.Encode(this.Dst); err != nil {
		return nil, err
	}
	if err := enc.Encode(this.TOS); err != nil {
		return nil, err
	}
	if err := enc.Encode(this.TTL); err != nil {
		return nil, err
	}
	if err := enc.Encode(this.Code); err != nil {
		return nil, err
	}
	if err := enc.Encode(this.ID); err != nil {
		return nil, err
	}
	if err := enc.Encode(this.Seq); err != nil {
		return nil, err
	}
	if err := enc.Encode(this.Size); err != nil {
		return nil, err
	}
	if err := enc.Encode(this.RTT); err != nil {
		return nil, err
	}
	if this.Err != nil {
		if err := enc.Encode(this.Err.Error()); err != nil {
			return nil, err
		}
	}
	return buf.Bytes(), nil
}
func (this PingResult) String() string {
	if this.Err != nil {
		return fmt.Sprintf("%v", this.Err)
	}
	return fmt.Sprintf("%d bytes from %v: seq=%d ttl=%d tos=%d time=%v",
		this.Size, this.Src, this.Seq, this.TTL, this.TOS, this.RTT)
}
type Pinger struct {
	iplist
	Interval time.Duration
	MaxRTT time.Duration
	Size int
	TOS int
	TTL int
	DF bool
	pid int64
	seqnum int32
	payload []byte
	wg sync.WaitGroup
	mu sync.Mutex
	done chan struct{}
	stopOnce *sync.Once
	quitOnce *sync.Once
	pconn net.PacketConn
	rconn *ipv4.RawConn
	reschan chan *PingResult
	results map[string]*PingResult
}
func (this *Pinger) Start() (<-chan *PingResult, error) {
	if !atomic.CompareAndSwapInt64(&this.pid, 0, int64(os.Getpid()&0xffff)) {
		return nil, fmt.Errorf("ping/Start: Pinger already running")
	}
	switch runtime.GOOS {
	case "nacl", "plan9", "solaris", "windows":
		return nil, fmt.Errorf("ping/Start: Operation not supported on %q", runtime.GOOS)
	}
	if os.Getuid() != 0 {
		return nil, fmt.Errorf("ping/Start: User must be root")
	}
	this.updateParams()
	if len(this.payload) < this.Size {
		this.payload = make([]byte, this.Size)
	} else {
		this.payload = this.payload[:this.Size]
	}
	var err error
	this.pconn, err = net.ListenPacket("ip4:icmp", "0.0.0.0")
	if err != nil {
		return nil, err
	}
	this.rconn, err = ipv4.NewRawConn(this.pconn)
	if err != nil {
		return nil, err
	}
	cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
	if err := this.rconn.SetControlMessage(cf, true); err != nil {
		return nil, err
	}
	this.wg.Add(1)
	go this.receiver()
	this.wg.Add(1)
	go this.sender()
	return this.reschan, nil
}