libf 2 年之前
父节点
当前提交
6551f98684
共有 7 个文件被更改,包括 267 次插入98 次删除
  1. 47 0
      ping/hosts.last.txt
  2. 6 1
      ping/hosts.txt
  3. 66 6
      ping/ping.go
  4. 16 8
      ping/probing/icmp/packetconn.go
  5. 11 9
      ping/probing/icmp/utils.go
  6. 23 11
      ping/probing/mpconn.go
  7. 98 63
      ping/probing/ping.go

+ 47 - 0
ping/hosts.last.txt

@@ -0,0 +1,47 @@
+127.0.0.1
+1.1.1.1
+8.26.56.26
+8.20.247.20
+64.6.64.6
+64.6.65.6
+192.95.54.3
+192.95.54.1
+8.8.8.8
+9.9.9.9
+84.200.69.80,84.200.70.40,81.218.119.11,209.88.198.133
+8.8.4.4,199.85.126.10,199.85.127.10,208.67.222.222,208.67.220.220
+baidu.com,qq.com,sohu.com,sogo.com,ali.com,taobao.com,cmcc.com,bing.com,csdn.net
+cnblogs.com,dns.com,zhihu.com,icoa.com,163.com,263.com,alipay.com
+tencent.com,west.com,west.cn,bilibili.com,ithome.com,meijumi.com.cn
+huawei.com,xiaomi.com,apple.com,apple.com.cn,netease.com,fanruan.com
+aliyun.com,eduyun.cn,mbalib.com,biocloud.net,ctyun.cn,baidu.cn,baihe.com
+php.cn,ibm.com,ibm.com.cn,sap.cn,topg.org,bing.com,hao123.com,cntv.cn
+iqiyi.com,yy.com,youku.com,mgtv.com,sohu.com,xiaodutv.com,gaodun.com
+58pic.com,docin.com,ctrip.com,12306.com,mafengwo.cn,tuniu.com,elong.com
+qyer.com,lvmama.com,csair.com,chinahr.com,lagou.com,liepin.com,mi.com
+eastmoney.com,stockstar.com,sina.com.cn,cnfol.com,xueqiu.com,fang.com,anjuke.com
+lianjia.com,ganji.com,xiachufang.com,baixing.com,dianping.com,meituan.com,tianyancha.com
+huanqiu.com,guancha.cn,lottery.gov.cn,cwl.gov.cn,icbc.com.cn,boc.com,ccb.com
+www.baidu.com,www.qq.com,www.sohu.com,www.sogo.com,www.ali.com,www.taobao.com,www.cmcc.com,www.bing.com,www.csdn.net
+www.cnblogs.com,www.dns.com,www.zhihu.com,www.icoa.com,www.163.com,www.263.com,www.alipay.com
+www.tencent.com,www.west.com,www.west.cn,www.bilibili.com,www.ithome.com,www.meijumi.com.cn
+www.huawei.com,www.xiaomi.com,www.apple.com,www.apple.com.cn,www.netease.com,www.fanruan.com
+www.aliyun.com,www.eduyun.cn,www.mbalib.com,www.biocloud.net,www.ctyun.cn,www.baidu.cn,www.baihe.com
+www.ibm.com,www.ibm.com.cn,www.sap.cn,www.topg.org,www.bing.com
+www.iqiyi.com,www.yy.com,www.youku.com,www.mgtv.com,www.sohu.com,www.xiaodutv.com,www.gaodun.com
+www.58pic.com,www.docin.com,www.ctrip.com,www.mafengwo.cn,www.tuniu.com,www.elong.com
+www.qyer.com,www.lvmama.com,www.csair.com,www.chinahr.com,www.lagou.com,www.liepin.com,www.mi.com
+www.eastmoney.com,www.stockstar.com,www.sina.com.cn,www.cnfol.com,www.xueqiu.com,www.fang.com,www.anjuke.com
+www.lianjia.com,www.ganji.com,www.xiachufang.com,www.baixing.com,www.dianping.com,www.meituan.com,www.tianyancha.com
+www.huanqiu.com,www.guancha.cn,www.lottery.gov.cn,www.cwl.gov.cn,www.icbc.com.cn,www.boc.com,www.ccb.com
+live.com,pan.baidu.com,hexun.com,
+kugou.com
+taihe.com
+baixing.com
+115.com
+le.com,wo.cn,yeah.net
+weiyun.com,weibo.com,189.cn,jianguoyun.com
+
+187.158.31.146,218.109.149.137
+60.217.223.70
+178.122.238.81

+ 6 - 1
ping/hosts.txt

@@ -40,4 +40,9 @@ taihe.com
 baixing.com
 115.com
 le.com,wo.cn,yeah.net
-weiyun.com,weibo.com,189.cn,jianguoyun.com
+weiyun.com,weibo.com,189.cn,jianguoyun.com
+
+187.158.31.146,218.109.149.137
+60.217.223.70
+178.122.238.81
+126.177.146.120

+ 66 - 6
ping/ping.go

@@ -3,6 +3,7 @@ package main
 import (
 	"encoding/json"
 	"fmt"
+	"math/rand"
 	"os"
 	"runtime"
 	"sort"
@@ -58,6 +59,7 @@ type Input struct {
 	ips           []string
 	statinfomutex sync.Mutex
 	statinfo      map[string]*StatInfo
+	ipaddrs       map[string]string
 	subSize       int
 	workChan      chan *task
 	stopChan      chan bool
@@ -66,28 +68,41 @@ type Input struct {
 
 var mcfg = cfg.MConfig()
 
+var allipsmutex sync.Mutex
+var allips = strset.New()
+
 func main() {
 	input := &Input{}
 	input.statinfo = map[string]*StatInfo{}
+	input.ipaddrs = map[string]string{}
 	inputcfg := &InputConfig{
 		Poolsize:     1000,
 		StatInterval: 600,
 	}
 	inputcfg.Poolsize = mcfg.GetInt("poolsize", inputcfg.Poolsize)
+	if mcfg.GetString("detect", "") == "1" {
+		go detect()
+	}
 	fips := func() []string {
 		xips := mcfg.GetStrings("ip|ping.ip", "")
-		sips := strset.New()
+		allipsmutex.Lock()
 		for _, aips := range xips {
-			sips.Add(strings.Split(aips, ",")...)
+			allips.Add(strings.Split(aips, ",")...)
 		}
 		bs, _ := util.ReadFile("./hosts.txt")
 		if len(bs) > 0 {
 			xips := strings.Split(string(bs), "\n")
 			for _, aips := range xips {
-				sips.Add(strings.Split(aips, ",")...)
+				allips.Add(strings.Split(aips, ",")...)
 			}
 		}
-		return sips.List()
+		if len(detectips) > 0 {
+			util.WriteFile("./hosts.txt", []byte(string(bs)+"\n"+strings.Join(detectips, ",")), true)
+			detectips = detectips[:0]
+		}
+		sips := allips.List()
+		allipsmutex.Unlock()
+		return sips
 	}
 	go func() {
 		t := time.NewTicker(5 * time.Second)
@@ -117,7 +132,8 @@ func main() {
 				sort.Strings(ks)
 				for i, k := range ks {
 					v := input.statinfo[k]
-					s += fmt.Sprintf("%-3d %-20s: %-12s [%12s ~ %-12s] loss %d/%d\n", i, k, v.AvgRtt, v.MinRtt, v.MaxRtt, v.LossCount, v.Count)
+					ip := input.ipaddrs[k]
+					s += fmt.Sprintf("%-3d %-20s %15s : %-12s [%12s ~ %-12s] loss %d/%d\n", i, k, ip, v.AvgRtt, v.MinRtt, v.MaxRtt, v.LossCount, v.Count)
 				}
 				input.statinfomutex.Unlock()
 				logger.Info("统计信息更新:", fmt.Sprint("\n", s))
@@ -133,6 +149,7 @@ func main() {
 	for {
 		if n >= len(input.ips) {
 			n = 0
+			input.ips = append(input.ips, detectips...)
 		}
 		ip := input.ips[n]
 		n++
@@ -141,7 +158,7 @@ func main() {
 		if ip != "" {
 			input.workChan <- &task{
 				Server:         ip,
-				Timeout:        mcfg.GetInt("timeout", 1),
+				Timeout:        mcfg.GetInt("timeout", 2),
 				NumberOfPings:  mcfg.GetInt("count", 5), // 至少为2,小于2会导致不能正常结束
 				PacketInterval: mcfg.GetInt("interval", 1000),
 				PacketSize:     mcfg.GetInt("size", 32),
@@ -267,6 +284,9 @@ func (input *Input) send(t *task, workerNum int) error {
 
 		pinger.OnSend = func(pkt *probing.Packet) {
 			recvMutex.Lock()
+			if recvList[pkt.Seq] != 0 {
+				println("并发控制有问题")
+			}
 			recvList[pkt.Seq]++
 			recvMutex.Unlock()
 			input.statinfomutex.Lock()
@@ -275,6 +295,7 @@ func (input *Input) send(t *task, workerNum int) error {
 				si = &StatInfo{}
 				input.statinfo[t.Server] = si
 			}
+			input.ipaddrs[t.Server] = pkt.IPAddr.String()
 			si.Count++
 			input.statinfomutex.Unlock()
 		}
@@ -327,6 +348,7 @@ func (input *Input) send(t *task, workerNum int) error {
 					Count:     0,
 				}
 				input.statinfo[t.Server] = si
+				input.ipaddrs[t.Server] = stats.IPAddr.String()
 			}
 			if stats.MinRtt > 0 && (si.MinRtt == 0 || stats.MinRtt < si.MinRtt) {
 				si.MinRtt = stats.MinRtt
@@ -392,3 +414,41 @@ func (input *Input) send(t *task, workerNum int) error {
 
 	return nil
 }
+
+var detectips = []string{}
+
+func detect() {
+	t := time.NewTicker(100 * time.Millisecond)
+	for {
+		<-t.C
+		randip := fmt.Sprintf("%d.%d.%d.%d", 1+rand.Intn(254), 1+rand.Intn(254), 1+rand.Intn(254), 1+rand.Intn(254))
+		allipsmutex.Lock()
+		has := allips.Has(randip)
+		allipsmutex.Unlock()
+		if !has {
+			if detectip(randip) {
+				allipsmutex.Lock()
+				detectips = append(detectips, randip)
+				allipsmutex.Unlock()
+			}
+		}
+	}
+}
+
+func detectip(addr string) (ok bool) {
+	pinger, err := probing.NewPinger(addr)
+	if err != nil {
+		return false
+	}
+	pinger.SetPrivileged(false)
+	pinger.TTL = 64
+	pinger.Count = 1
+	pinger.Interval = 200 * time.Millisecond
+	pinger.Size = 32
+	pinger.Timeout = 1 * time.Second
+	pinger.OnRecv = func(pkt *probing.Packet) {
+		ok = true
+	}
+	pinger.Run()
+	return
+}

+ 16 - 8
ping/probing/icmp/packetconn.go

@@ -8,6 +8,7 @@ import (
 	"syscall"
 	"time"
 
+	"github.com/google/uuid"
 	"golang.org/x/net/icmp"
 	"golang.org/x/net/ipv4"
 	"golang.org/x/net/ipv6"
@@ -58,10 +59,14 @@ type Packet struct {
 	ID int
 	// Seq is the ICMP sequence number.
 	Seq int
+	// UUID
+	UUID uuid.UUID
 	// TTL is the Time To Live on the packet.
 	TTL int
 	// NBytes is the number of bytes in the message.
 	Nbytes int
+	// SendTime
+	SendTime time.Time
 	// Rtt is the round-trip time it took to ping.
 	Rtt time.Duration
 }
@@ -170,7 +175,7 @@ func (mp *MPacketConn) SendPacket(pkt *Packet) error {
 	if mp.conn == nil {
 		return ENOLISTENER
 	}
-	msgBytes, err := BuildEchoRequestMessage(pkt.ID, pkt.Seq, pkt.Nbytes, mp.conn.ICMPRequestType())
+	msgBytes, err := pkt.BuildEchoRequestMessage(mp.conn.ICMPRequestType())
 	if err != nil {
 		return err
 	}
@@ -248,13 +253,14 @@ func (mp *MPacketConn) processPacket(recv *recvPkt) error {
 }
 
 func (mp *MPacketConn) processEchoReply(pkt *icmp.Echo, recv *recvPkt) error {
-	if len(pkt.Data) < 24 {
+	if len(pkt.Data) < 40 {
 		return nil
 	}
 
 	sendtime := int64(binary.BigEndian.Uint64(pkt.Data[:8]))
 	fullseq := int(binary.BigEndian.Uint64(pkt.Data[8:16]))
 	fullid := int(binary.BigEndian.Uint64(pkt.Data[16:24]))
+	pktuuid := uuid.Must(uuid.FromBytes(pkt.Data[24:40]))
 
 	if fullid%65536 != pkt.ID || fullseq%65536 != pkt.Seq {
 		return nil
@@ -265,12 +271,14 @@ func (mp *MPacketConn) processEchoReply(pkt *icmp.Echo, recv *recvPkt) error {
 
 	if mp.OnRecvPacket != nil {
 		mp.OnRecvPacket(&Packet{
-			IPAddr: netAddrToIPAddr(recv.addr),
-			ID:     fullid,
-			Seq:    fullseq,
-			Nbytes: recv.nbytes,
-			TTL:    recv.ttl,
-			Rtt:    recv.recvtime.Sub(time.Unix(0, sendtime)),
+			IPAddr:   netAddrToIPAddr(recv.addr),
+			ID:       fullid,
+			Seq:      fullseq,
+			UUID:     pktuuid,
+			Nbytes:   recv.nbytes,
+			TTL:      recv.ttl,
+			SendTime: time.Unix(0, sendtime),
+			Rtt:      recv.recvtime.Sub(time.Unix(0, sendtime)),
 		})
 	}
 	return nil

+ 11 - 9
ping/probing/icmp/utils.go

@@ -19,18 +19,20 @@ func netAddrToIPAddr(a net.Addr) *net.IPAddr {
 	return nil
 }
 
-func BuildEchoRequestMessage(id, seq, size int, icmptype Type) ([]byte, error) {
-	if size < 24 {
-		size = 24
+func (pkt *Packet) BuildEchoRequestMessage(icmptype Type) ([]byte, error) {
+	if pkt.Nbytes < 40 {
+		pkt.Nbytes = 40
 	}
-	bs := bytes.Repeat([]byte{1}, size)
-	binary.BigEndian.PutUint64(bs, uint64(time.Now().UnixNano()))
-	binary.BigEndian.PutUint64(bs[8:], uint64(seq))
-	binary.BigEndian.PutUint64(bs[16:], uint64(id))
+	bs := bytes.Repeat([]byte{1}, pkt.Nbytes)
+	pkt.SendTime = time.Now()
+	binary.BigEndian.PutUint64(bs, uint64(pkt.SendTime.UnixNano()))
+	binary.BigEndian.PutUint64(bs[8:], uint64(pkt.Seq))
+	binary.BigEndian.PutUint64(bs[16:], uint64(pkt.ID))
+	copy(bs[24:], pkt.UUID[:])
 
 	body := &icmp.Echo{
-		ID:   id % 65535,
-		Seq:  seq % 65536,
+		ID:   pkt.ID % 65535,
+		Seq:  pkt.Seq % 65536,
 		Data: bs,
 	}
 

+ 23 - 11
ping/probing/mpconn.go

@@ -1,7 +1,7 @@
 package probing
 
 import (
-	"fmt"
+	"bytes"
 	"net"
 	"sync"
 	"sync/atomic"
@@ -9,6 +9,7 @@ import (
 	"trial/ping/probing/icmp"
 
 	"git.wecise.com/wecise/common/logger"
+	"github.com/google/uuid"
 )
 
 var connm sync.Mutex
@@ -34,6 +35,7 @@ func MPConn(ipv4 bool, protocol string) *mpingconn {
 type mpingconn struct {
 	*icmp.MPacketConn
 	mutex      sync.Mutex
+	uuid       uuid.UUID
 	pingidinfo map[int]*mpinfo
 }
 
@@ -52,17 +54,22 @@ type mpinfo struct {
 }
 
 var pingid int32
-var ETIMEDOUT error = fmt.Errorf("timeout")
-
-func newPingInfo(host string, ipaddr *net.IPAddr, size int, timeout time.Duration) *mpinfo {
-	return &mpinfo{
-		host:    host,
-		ipaddr:  ipaddr,
-		id:      int(atomic.AddInt32(&pingid, 1)),
-		seqpkt:  make(map[int]*icmp.Packet),
-		size:    size,
-		timeout: timeout,
+var pinginfomutex sync.Mutex
+var pinginfo = map[string]*mpinfo{}
+
+func getPingInfo(ipaddr *net.IPAddr) *mpinfo {
+	pinginfomutex.Lock()
+	defer pinginfomutex.Unlock()
+	pinfo := pinginfo[ipaddr.String()]
+	if pinfo == nil {
+		pinfo = &mpinfo{
+			ipaddr: ipaddr,
+			id:     int(atomic.AddInt32(&pingid, 1)),
+			seqpkt: make(map[int]*icmp.Packet),
+		}
+		pinginfo[ipaddr.String()] = pinfo
 	}
+	return pinfo
 }
 
 func newMPConn(ipv4 bool, protocol string) *mpingconn {
@@ -74,6 +81,7 @@ func newMPConn(ipv4 bool, protocol string) *mpingconn {
 			Backlog:  10,
 			TTL:      64,
 		},
+		uuid:       uuid.Must(uuid.NewUUID()),
 		pingidinfo: make(map[int]*mpinfo),
 	}
 	mpconn.MPacketConn.OnRecvPacket = mpconn.OnRecvPacket
@@ -107,6 +115,9 @@ func (p *mpingconn) OnRecvPacket(recvpkt *icmp.Packet) {
 	if pinfo == nil {
 		return
 	}
+	if !bytes.Equal(p.uuid[:], recvpkt.UUID[:]) {
+		return
+	}
 	_, inflight := pinfo.seqpkt[recvpkt.Seq]
 	if inflight {
 		// remove it from the list of sequences we're waiting for so we don't get duplicates.
@@ -136,6 +147,7 @@ func (p *mpingconn) Ping(pinfo *mpinfo) error {
 		IPAddr: pinfo.ipaddr,
 		ID:     pinfo.id,
 		Seq:    seq,
+		UUID:   p.uuid,
 		Nbytes: pinfo.size,
 	}
 	pinfo.seqpkt[seq] = outpkt

+ 98 - 63
ping/probing/ping.go

@@ -53,6 +53,7 @@ package probing
 
 import (
 	"errors"
+	"fmt"
 	"math"
 	"math/rand"
 	"net"
@@ -72,13 +73,11 @@ var receive_buffer_count = mcfg.GetInt("ping.recv.buf.count", 100)
 var ttl = mcfg.GetInt("ping.ttl", 64)
 var ping_interval = mcfg.GetDuration("ping.interval", 1000*time.Millisecond)
 var concurlimit_ping = mcfg.GetInt("concurlimit.ping", 100)
-var concurlimit_send = mcfg.GetInt("concurlimit.send", 10)
 var concurchan_ping = make(chan struct{}, concurlimit_ping)
-var concurchan_send = make(chan struct{}, concurlimit_send)
 var lastpingtimemutex sync.Mutex
 var lastpingtime = map[string]time.Time{}
-var lastsendtimemutex sync.Mutex
-var lastsendtime = map[string]time.Time{}
+
+var ETIMEDOUT error = fmt.Errorf("timeout")
 
 const (
 	timeSliceLength = 8
@@ -389,10 +388,38 @@ func (p *Pinger) ID() int {
 	return p.id
 }
 
+var pingipmtx sync.Mutex
+var pingips = map[string]chan interface{}{}
+var pingads = map[string]chan interface{}{}
+
 // Run runs the pinger. This is a blocking function that will exit when it's
 // done. If Count or Interval are not specified, it will run continuously until
 // it is interrupted.
-func (p *Pinger) Run() error {
+func (p *Pinger) Run() (err error) {
+	// 同一地址,只能有一个实例运行,排队等待
+	pingipmtx.Lock()
+	pingipchan := pingips[p.ipaddr.String()]
+	if pingipchan == nil {
+		pingipchan = make(chan interface{}, 1)
+		pingips[p.ipaddr.String()] = pingipchan
+	}
+	pingadchan := pingads[p.addr]
+	if pingadchan == nil {
+		pingadchan = make(chan interface{}, 1)
+		pingads[p.addr] = pingadchan
+	}
+	pingipmtx.Unlock()
+	pingipchan <- 1
+	pingadchan <- 1
+	var last_send_time time.Time
+	defer func() {
+		d := p.Interval - time.Since(last_send_time)
+		if d > 0 {
+			time.Sleep(d) // 两次运行之间至少间隔
+		}
+		<-pingipchan
+		<-pingadchan
+	}()
 	// sleeptime := time.Duration(0)
 	// for sleeptime >= 0 {
 	// 	time.Sleep(sleeptime)
@@ -415,15 +442,16 @@ func (p *Pinger) Run() error {
 	// defer func() {
 	// 	<-concurchan_ping
 	// }()
-	return p.run()
+	last_send_time, err = p.run()
+	return
 }
 
-func (p *Pinger) run() error {
+func (p *Pinger) run() (time.Time, error) {
 	defer p.finish()
 
 	err := MPConn(p.ipv4, p.protocol).Listen()
 	if err != nil {
-		return err
+		return time.Time{}, err
 	}
 
 	if handler := p.OnSetup; handler != nil {
@@ -431,16 +459,18 @@ func (p *Pinger) run() error {
 	}
 
 	var g errgroup.Group
+	var last_send_time time.Time
 
-	g.Go(func() error {
+	g.Go(func() (err error) {
 		defer p.Stop()
-		return p.runLoop()
+		last_send_time, err = p.runLoop()
+		return err
 	})
 
-	return g.Wait()
+	return last_send_time, g.Wait()
 }
 
-func (p *Pinger) runLoop() error {
+func (p *Pinger) runLoop() (time.Time, error) {
 
 	timeout := time.NewTimer(p.Timeout)
 	interval := time.NewTimer(0)
@@ -451,54 +481,13 @@ func (p *Pinger) runLoop() error {
 	}()
 	received := make(chan interface{}, 1)
 
-	for {
-		select {
-		case <-p.done:
-			return nil
-
-		case <-timeout.C:
-			return nil
-
-		case <-interval.C:
-			if err := p.ping(received); err != nil {
-				logger.Errorf("sending packet: %s", err)
-			}
-			if p.Count > 0 && p.PacketsSent >= p.Count {
-				timeout.Reset(p.Timeout)
-			} else {
-				interval.Reset(p.Interval)
-			}
-		case <-received:
-			if p.Count > 0 && p.PacketsRecv >= p.Count {
-				return nil
-			}
-		}
-	}
-}
-
-func (p *Pinger) ping(received chan interface{}) error {
-
-	sleeptime := time.Duration(0)
-	for sleeptime >= 0 {
-		time.Sleep(sleeptime)
-		lastpingtimemutex.Lock()
-		alastpingtime := lastpingtime[p.ipaddr.String()]
-		sleeptime = ping_interval - time.Since(alastpingtime)
-		if sleeptime <= 0 {
-			lastpingtime[p.ipaddr.String()] = time.Now()
-		} else {
-			// logger.Error(fmt.Sprint("ping", p.addr, "[", p.ipaddr.String(), "]", "同一地址至少间隔一秒"))
-		}
-		lastpingtimemutex.Unlock()
-	}
-	defer func() {
-		lastpingtimemutex.Lock()
-		lastpingtime[p.ipaddr.String()] = time.Now()
-		lastpingtimemutex.Unlock()
-	}()
-
-	pinfo := newPingInfo(p.addr, p.ipaddr, p.Size, p.Timeout)
+	last_send_time := time.Now()
+	pinfo := getPingInfo(p.ipaddr)
+	pinfo.host = p.addr
+	pinfo.size = p.Size
+	pinfo.timeout = p.Timeout
 	pinfo.OnSend = func(pkt *icmp.Packet) {
+		last_send_time = pkt.SendTime
 		if p.PacketsSent == 0 {
 			p.sequence_base = pkt.Seq
 		}
@@ -507,7 +496,7 @@ func (p *Pinger) ping(received chan interface{}) error {
 			p.OnSend(&Packet{
 				Rtt:    pkt.Rtt,
 				IPAddr: pkt.IPAddr,
-				Host:   pinfo.host,
+				Host:   p.addr,
 				Nbytes: pkt.Nbytes,
 				Seq:    pkt.Seq - p.sequence_base,
 				TTL:    pkt.TTL,
@@ -519,7 +508,7 @@ func (p *Pinger) ping(received chan interface{}) error {
 		inpkt := &Packet{
 			Rtt:    pkt.Rtt,
 			IPAddr: pkt.IPAddr,
-			Host:   pinfo.host,
+			Host:   p.addr,
 			Nbytes: pkt.Nbytes,
 			Seq:    pkt.Seq - p.sequence_base,
 			TTL:    pkt.TTL,
@@ -535,7 +524,7 @@ func (p *Pinger) ping(received chan interface{}) error {
 		inpkt := &Packet{
 			Rtt:    pkt.Rtt,
 			IPAddr: pkt.IPAddr,
-			Host:   pinfo.host,
+			Host:   p.addr,
 			Nbytes: pkt.Nbytes,
 			Seq:    pkt.Seq - p.sequence_base,
 			TTL:    pkt.TTL,
@@ -546,9 +535,55 @@ func (p *Pinger) ping(received chan interface{}) error {
 		}
 		p.updateStatistics(inpkt)
 	}
-	return MPConn(p.ipv4, p.protocol).Ping(pinfo)
+	for {
+		select {
+		case <-p.done:
+			return last_send_time, nil
+
+		case <-timeout.C:
+			return last_send_time, nil
+
+		case <-interval.C:
+			if p.Count > 0 && p.PacketsSent >= p.Count {
+				timeout.Reset(p.Timeout)
+			} else {
+				if err := MPConn(p.ipv4, p.protocol).Ping(pinfo); err != nil {
+					logger.Errorf("sending packet: %s", err)
+				}
+				interval.Reset(p.Interval)
+			}
+		case <-received:
+			if p.Count > 0 && p.PacketsRecv >= p.Count {
+				return last_send_time, nil
+			}
+		}
+	}
 }
 
+// func (p *Pinger) ping(pinfo *mpinfo, received chan interface{}) error {
+
+// sleeptime := time.Duration(0)
+// for sleeptime >= 0 {
+// 	time.Sleep(sleeptime)
+// 	lastpingtimemutex.Lock()
+// 	alastpingtime := lastpingtime[p.ipaddr.String()]
+// 	sleeptime = ping_interval - time.Since(alastpingtime)
+// 	if sleeptime <= 0 {
+// 		lastpingtime[p.ipaddr.String()] = time.Now()
+// 	} else {
+// 		// logger.Error(fmt.Sprint("ping", p.addr, "[", p.ipaddr.String(), "]", "同一地址至少间隔一秒"))
+// 	}
+// 	lastpingtimemutex.Unlock()
+// }
+// defer func() {
+// 	lastpingtimemutex.Lock()
+// 	lastpingtime[p.ipaddr.String()] = time.Now()
+// 	lastpingtimemutex.Unlock()
+// }()
+
+// return MPConn(p.ipv4, p.protocol).Ping(pinfo)
+// }
+
 func (p *Pinger) Stop() {
 	p.lock.Lock()
 	defer p.lock.Unlock()