pingclient

package module
v0.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2021 License: MIT Imports: 16 Imported by: 0

README


GoDoc reference example Go Report Card

PingClient是一款基于Go语言的发送ICMP ping的库,可以自定义配置ping相关的参数并且可同时设置多个IP地址或者是URL,以及包含ping相关的数据分析如RTT(Round-trip time)等。Inspired by go-fastping and go-ping 欢迎PR, Star, Issue

Key features:

  1. 支持Yaml配置ping相关参数以及地址等,一键启动
  2. 可同时配置多个ping的IP或者URL地址以及不同ping的策略, IP地址和URL可以混合
  3. 减少goroutine的数量,降低cpu负载
  4. 支持ping包的数据统计,RTT、packet loss, ttl等

目录

展开目录简介

安装

使用go get安装:

go get -u -v github.com/scientiacoder/go-PingClient

使用git clone下载到本地:

git clone https://github.com/scientiacoder/go-PingClient
cd go-PingClient/

运行

使用Yaml配置启动PingClient

推荐使用Yaml文件配置启动PingClient,参见文件夹下config.yaml以及config.example.yaml

展开使用Yaml配置启动PingClient
配置ping单一IP地址或者URL

假设ping IP地址220.181.38.148 5次时间间隔为200ms发一个包
config.yaml设置为:

app:
  pingClient1:
    interval:
      200   # ping发包的时间间隔,单位毫秒
    timeout:
      5000 # ping如果超时会在经过这个时间后自动退出,单位毫秒
    ips:
      220.181.38.148
    num:
      5 # ping每个地址发包的次数

之后运行:

go run cmd/ping.go config.yaml

样例输出:

PING 220.181.38.148:
24 bytes from 220.181.38.148: icmp_seq=4722 time=192.073801ms ttl=40
24 bytes from 220.181.38.148: icmp_seq=4723 time=189.523571ms ttl=40
24 bytes from 220.181.38.148: icmp_seq=4724 time=176.11971ms ttl=40
24 bytes from 220.181.38.148: icmp_seq=4725 time=181.480174ms ttl=40
24 bytes from 220.181.38.148: icmp_seq=4726 time=181.702277ms ttl=40

---  220.181.38.148 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 176.11971ms/184.179906ms/192.073801ms/5.818286ms

同样,如果想ping URL地址为www.github.com,只需配置config.yaml

app:
  pingClient1:
    interval:
      200   # ping发包的时间间隔,单位毫秒
    timeout:
      5000 # ping如果超时会在经过这个时间后自动退出,单位毫秒
    urls:
      www.github.com
    num:
      5 # ping每个地址发包的次数
go run cmd/ping.go config.yaml

得到输出:

PING www.github.com 13.237.44.5:
24 bytes from 13.237.44.5: icmp_seq=4722 time=40.532569ms ttl=40
24 bytes from 13.237.44.5: icmp_seq=4723 time=36.492822ms ttl=40
24 bytes from 13.237.44.5: icmp_seq=4724 time=43.692405ms ttl=40
24 bytes from 13.237.44.5: icmp_seq=4725 time=55.602643ms ttl=40
24 bytes from 13.237.44.5: icmp_seq=4726 time=38.508645ms ttl=40

--- www.github.com 13.237.44.5 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 36.492822ms/42.965816ms/55.602643ms/6.751356ms
配置同时ping多个IP地址或者URL

同时ping多个IP地址只需配置config.yaml

app:
  pingClient1:
    interval:
      200   # ping发包的时间间隔,单位毫秒
    timeout:
      5000 # ping如果超时会在经过这个时间后自动退出,单位毫秒
    ips:
      220.181.38.148
      13.237.44.5
    num:
      5 # ping每个地址发包的次数
go run cmd/ping.go config.yaml

同时ping多个URL只需配置config.yaml的urls

app:
  pingClient1:
    interval:
      200   # ping发包的时间间隔,单位毫秒
    timeout:
      5000 # ping如果超时会在经过这个时间后自动退出,单位毫秒
    urls:
      github.com
      golang.org
      baidu.com
    num:
      5 # ping每个地址发包的次数
go run cmd/ping.go config.yaml

IP和URL混合ping

app:
  pingClient1:
    interval:
      200   # ping发包的时间间隔,单位毫秒
    timeout:
      5000 # ping如果超时会在经过这个时间后自动退出,单位毫秒
    ips:
      220.181.38.148
      13.237.44.5
    urls:
      github.com
      golang.org
    num:
      5 # ping每个地址发包的次数
go run cmd/ping.go config.yaml
配置同时使用多个PingClient

config.yaml:

app:
  pingClient1:
    interval:
      200   # in milliseconds (ping发包的时间间隔,单位毫秒)
    timeout:
      5000   # in milliseconds Timeout specifies a timeout before ping exits (ping会在经过这个时间后自动退出,单位毫秒)
    ips:
      142.250.71.78
      220.181.38.148
    urls:
      www.github.com
      www.stackoverflow.com
      golang.org
    num:
      5 # number of packets send per ip(or url) (ping每个地址的次数)
    privileged:
      false # false uses udp ping, true uses icmp raw socket need privilege (false基于udp, true需要权限使用原生socket)
    continuous:
      false # true means it will ping addresses continuously, ignore the num (default: false) (true表示会一直ping下去, 忽略num, 默认是false)
  pingClient2:
    ips:
      142.250.71.78
      220.181.38.148
  pingClient3:
    urls:
      google.com
  pingClient4:
    urls:
      github.com
    privileged:
      false
go run cmd/ping.go config.yaml
使用命令行启动PingClient

命令行启动例子go run cmd/ping.go github.com
其中命令行支持多种参数启动

-t 表示timeout时间自动退出 如: -t 5000ms
-i 表示interval发包时间间隔: -i 500ms
-n 表示要发送的包的数量: -n 6
-c 表示continuous, 如果启动命令带有-c 则会一直ping下去直到Ctrl+c终止 忽略要发送的包数量
-privileged 表示是否使用ICMP原生socket, 需要root权限,默认是使用的udp封装的而不是原生socket -privileged启动使用原生socket
展开使用命令行启动PingClient
命令行ping单一IP地址或者URL

如果想ping github.com 6次, 时间间隔为1s, 运行:

go run cmd/ping.go -n 6 -i 1s github.com

该命令中github.com可改为任意IP地址 输出为:

PING github.com 13.237.44.5:
24 bytes from 13.237.44.5: icmp_seq=4722 time=35.127904ms ttl=41
24 bytes from 13.237.44.5: icmp_seq=4723 time=36.252251ms ttl=41
24 bytes from 13.237.44.5: icmp_seq=4724 time=29.305253ms ttl=41
24 bytes from 13.237.44.5: icmp_seq=4725 time=37.577805ms ttl=41
24 bytes from 13.237.44.5: icmp_seq=4726 time=45.584345ms ttl=41
24 bytes from 13.237.44.5: icmp_seq=4727 time=33.345722ms ttl=41

--- github.com 13.237.44.5 ping statistics ---
6 packets transmitted, 6 packets received, 0% packet loss
round-trip min/avg/max/stddev = 29.305253ms/36.19888ms/45.584345ms/4.946393ms

如果想持续ping github.com, 时间间隔为1s(Ctrl+c终止), 运行:

go run cmd/ping.go -i 1s -c github.com
命令行同时ping多个IP地址或者URL

只需将多个IP地址或者URL放在命令最后即可,运行:

go run cmd/ping.go -i 1s -c github.com golang.org 13.237.44.5
命令行ping使用ICMP原生socket

首先确认go get在root用户的PATH下也安装了PingClient包

sudo go get -u -v github.com/scientiacoder/PingClient

之后即可sudo运行-privileged选项

sudo go run cmd/ping.go -i 1s -privileged -c github.com

程序内引用PingClient并启动

展开程序内引用PingClient并启动

在程序内引用首先确保PingClient包已装:

go get -u -v github.com/scientiacoder/PingClient

之后可以import PingClient包

import ping "github.com/scientiacoder/PingClient"

以下是一个同时ping github.com和IP 8.8.8.8, 发包时间间隔为200ms的完整示例:

package main

import (
	"fmt"
	"log"
	"time"

	ping "github.com/scientiacoder/PingClient"
)

func main() {
	pingClient := ping.New()
	err := pingClient.Add("github.com")
	if err != nil {
		log.Fatalf("%s", err)
		return
	}
	err = pingClient.Add("8.8.8.8")
	if err != nil {
		log.Fatalf("%s", err)
		return
	}

	pingClient.Interval = 200 * time.Millisecond
	pingClient.OnRecv = func(pkt *ping.Packet) {
		fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v ttl=%v\n",
			pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt, pkt.Ttl)
	}
	pingClient.OnFinish = func(stats []*ping.Statistics) {
		for _, stat := range stats {
			fmt.Printf("\n--- %s %s ping statistics ---\n", stat.URL, stat.IP)
			fmt.Printf("%d packets transmitted, %d packets received, %v%% packet loss\n",
				stat.PacketsSent, stat.PacketsRecv, stat.PacketLoss)
			fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n",
				stat.MinRtt, stat.AvgRtt, stat.MaxRtt, stat.StdDevRtt)
		}
	}

	err = pingClient.Run()
	if err != nil {
		log.Fatalf("%s", err)
		return
	}
}

支持的操作系统

Linux

在默认情况下,此PingClient试图发送non-Privileged(非root) Ping通过UDP,因此需要通过以下sysctl命令来设置:

sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"

否则的话可能会出现以下socket错误因为Linux桌面版做了一些限制:

socket: permission denied

Mac OSX

可直接运行

go run cmd/ping.go config.yaml

Windows

在Windows平台上,必须要把privileged设置为true,不管是通过Yaml, 命令行方式运行
如果是在程序内引用,请添加一行代码:

pingClient.SetPrivileged(true)

否则的话可能会出现以下socket错误

socket: The requested protocol has not been configured into the system, or no implementation for it exists.

TODO

  • English README
  • IPv6 Support
  • Unit Test
  • Benchmark
  • OnTimeout(heartbeat check)

贡献

该项目目前由@scientiacoder维护,欢迎PR, Star, Issue Welcome

许可协议

MIT

Documentation

Overview

Package pingclient is a simple but powerful ICMP echo (ping) library. Inspired by go-fastping and go-ping

Here is a very simple example that sends and receives three packets:

import ping "github.com/scientiacoder/PingClient"

pingClients, err := ping.InitWithYAMLFile("config.yaml")
if err != nil {
	log.Fatalf("%s", err)
	return
}
for _, pingClient := range pingClients {
		pingClient.OnRecv = func(pkt *ping.Packet) {
			fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v ttl=%v\n",
				pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt, pkt.Ttl)
	}
}
for _, pingClient := range pingClients {
	err := pingClient.Run()
	if err != nil {
		log.Fatalf("%s", err)
		return
	}
}

Here is an example that pings github.com and 8.8.8.8 command:

pingClient := ping.New() pingClient.Add("github.com") pingClient.Add("8.8.8.8")

// Listen for Ctrl-C. c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt)

go func() {
	   for _ = range c {
		   pingClient.Stop()
	   }
}()
pingClient.OnRecv = func(pkt *ping.Packet) {
	   fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v ttl=%v\n",
		   pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt, pkt.Ttl)
}

pingClient.OnFinish = func(stats []*ping.Statistics) {

for _, stat := range stats {
	   fmt.Printf("\n--- %s %s ping statistics ---\n", stat.URL, stat.IP)
	   for _, pkt := range stat.PacketsInfo {
		   fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v ttl=%v\n",
			   pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt, pkt.Ttl)
	   }
	   fmt.Printf("%d packets transmitted, %d packets received, %v%% packet loss\n",
		   stat.PacketsSent, stat.PacketsRecv, stat.PacketLoss)
	   fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n",
		   stat.MinRtt, stat.AvgRtt, stat.MaxRtt, stat.StdDevRtt)
    }
}

err := pingClient.Run()

if err != nil {
	  log.Fatalf("%s", err)
	  return
}

It sends ICMP Echo Request packet(s) and waits for an Echo Reply in response. If it receives a response, it calls the OnRecv callback. When it's finished, it calls the OnFinish callback.

For a full ping example, see "cmd/ping.go".

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All(m map[string]int, f func(int, int) bool, num int) bool

All checks whether all the map entry satisfies the function f

func Use

func Use(args ...interface{})

Use simply resolves xx declared but not used issue for debug

Types

type Config

type Config struct {
	PingClientsConf []*PingClientConfig
}

Config helps parsing config.yaml or config.yml It will convert yaml file to a list of PingClientConfig

func NewConfig

func NewConfig() *Config

NewConfig returns an instance of Config which includes list of PingClientConfig

func ParseConfig

func ParseConfig(conf map[interface{}]interface{}) (*Config, error)

ParseConfig parses config from yaml file

type Packet

type Packet struct {
	// Rtt is the round-trip time it took to ping.
	Rtt time.Duration

	// IPAddr is the address of the host being pinged.
	IPAddr *net.IPAddr

	// IP address in string format e.g "142.250.71.78"
	IP string

	// NBytes is the number of bytes in the message.
	Nbytes int

	// Seq is the ICMP sequence number.
	Seq int

	// TTL is the Time To Live on the packet.
	Ttl int
}

Packet represents a received and processed ICMP echo packet.

type PingClient

type PingClient struct {
	// Interval is the wait time between each packet send. Default is 1s.
	Interval time.Duration

	// Timeout specifies a timeout before ping exits, regardless of how many
	// packets have been received.
	Timeout time.Duration

	// Count tells PingClient to stop after sending (and receiving) Count echo
	// packets. If this option is not specified, PingClient will operate until
	// interrupted.
	Count int

	// number of packets send per ip(or url) address
	Num int

	// Debug runs in debug mode
	Debug bool

	// Number of packets sent
	PacketsSent map[string]int

	// Number of packets received
	PacketsRecv map[string]int

	// Received packets info for Statistics use
	PacketsInfo map[string][]*Packet

	// If true, keep a record of rtts of all received packets.
	// Set to false to avoid memory bloat for long running pings.
	RecordRtts bool

	// OnRecv is called when PingClient receives and processes a packet
	OnRecv func(*Packet)

	// OnFinish is called when PingClient exits
	OnFinish func([]*Statistics)

	// Size of packet being sent
	Size int

	// Tracker: Used to uniquely identify packet when non-priviledged
	Tracker int64

	// Source is the source IP address
	Source string

	// list of destination ping IPs
	IPs []*net.IPAddr

	// list of destination ping URLs
	URLs []string

	IPToURL map[string]string

	// whether run Continuously(forever)
	Continuous bool
	// contains filtered or unexported fields
}

PingClient represents a packet sender/receiver.

func InitWithConfig

func InitWithConfig(conf *Config) []*PingClient

InitWithConfig inits list of ping clients configured by the yaml file

func InitWithYAMLFile

func InitWithYAMLFile(name string) ([]*PingClient, error)

InitWithYAMLFile inits a ping client with given yaml file

func New

func New() *PingClient

New returns a new PingClient struct pointer.

func NewPingClient

func NewPingClient(addr string) (*PingClient, error)

NewPingClient returns a new PingClient struct pointer and resolves string addr

func NewPingClientWithConfig

func NewPingClientWithConfig(conf *PingClientConfig) *PingClient

NewPingClientWithConfig uses struct PingClientConfig to create a new PingClient

func NewPrivilegedPingClient

func NewPrivilegedPingClient(addr string) (*PingClient, error)

NewPrivilegedPingClient returns a new raw socket PingClient struct pointer and resolves string addr

func (*PingClient) Add

func (p *PingClient) Add(addr string) error
  • * * * * * * * * * * * * * * * * * * * * * _____ _____ _ _ _ _ _ |_ _| __ \ | | | | | (_) | | | | |__) | | | | | |_ _| |___ | | | ___/ | | | | __| | / __| _| |_| | | |__| | |_| | \__ \ |_____|_| \____/ \__|_|_|___/

* * * * * * * * * * * * * * * * * * * * * * Add parses addr(ip format or url format) to net.IP and adds net.IP to pingClient

func (*PingClient) AddIPAddr

func (p *PingClient) AddIPAddr(addr string) error

AddIPAddr adds IP address to ping client

func (*PingClient) AddURLAddr

func (p *PingClient) AddURLAddr(addr string) error

AddURLAddr resolves URL addr to IP address and adds IP address to ping client

func (*PingClient) Privileged

func (p *PingClient) Privileged() bool

Privileged returns whether PingClient is running in privileged mode.

func (*PingClient) Run

func (p *PingClient) Run() error

Run runs the PingClient. This is a blocking function that will exit when it's done.

func (*PingClient) SetNetwork

func (p *PingClient) SetNetwork(n string)

SetNetwork allows configuration of DNS resolution. * "ip" will automatically select IPv4 or IPv6. * "ip4" will select IPv4. * "ip6" will select IPv6.

func (*PingClient) SetPrivileged

func (p *PingClient) SetPrivileged(privileged bool)

SetPrivileged sets the type of ping PingClient will send. false means PingClient will send an "unprivileged" UDP ping. true means PingClient will send a "privileged" raw ICMP ping. NOTE: setting to true requires that it be run with super-user privileges.

func (*PingClient) SetRecordRtts

func (p *PingClient) SetRecordRtts(r bool)

SetRecordRtts sets whether record Statistics

func (*PingClient) Statistics

func (p *PingClient) Statistics() []*Statistics

Statistics returns the statistics of the whole PingClient. This can be run while the PingClient is running or after it is finished. OnFinish calls this function to get it's finished statistics.

func (*PingClient) StatisticsPerIP

func (p *PingClient) StatisticsPerIP(ipAddr *net.IPAddr) *Statistics

StatisticsPerIP returns the statistics of the Ping info to the given IP address.

func (*PingClient) Stop

func (p *PingClient) Stop()

Stop the ping client

type PingClientConfig

type PingClientConfig struct {
	// time interval of sending packets in milliseconds
	Interval time.Duration

	// timeout indicates the maximum waiting response time
	Timeout time.Duration

	// ip addresses of pinged endpoints
	IPs []*net.IPAddr

	// urls being pinged
	URLs []string

	// number of packets be going to send
	Num int

	// inverted index after resolve IP address of URL
	IPToURL map[string]string

	// whether run continuously(forever)
	Continuous bool

	// privileged uses icmp raw socket to ping while non-privileged uses udp
	Privileged bool
}

PingClientConfig represents config struct for single PingClient

func NewDefaultPingClientConfig

func NewDefaultPingClientConfig() *PingClientConfig

NewDefaultPingClientConfig inits a PingClientConfig with default value

type Statistics

type Statistics struct {
	// PacketsRecv is the number of packets received.
	PacketsRecv int

	// PacketsSent is the number of packets sent.
	PacketsSent int

	// PacketLoss is the percentage of packets lost.
	PacketLoss float64

	// Received packets info for Statistics use
	PacketsInfo []*Packet

	// URL is the URL address of the host being pinged.
	URL string

	// IP address in string format e.g "142.250.71.78"
	IP string

	// Rtts is all of the round-trip times sent via this PingClient.
	Rtts []time.Duration

	// MinRtt is the minimum round-trip time sent via this PingClient.
	MinRtt time.Duration

	// MaxRtt is the maximum round-trip time sent via this PingClient.
	MaxRtt time.Duration

	// AvgRtt is the average round-trip time sent via this PingClient.
	AvgRtt time.Duration

	// StdDevRtt is the standard deviation of the round-trip times sent via
	// this PingClient.
	StdDevRtt time.Duration
}

Statistics represent the stats of a currently running or finished PingClient operation.

type StatisticsList

type StatisticsList struct {
	// contains filtered or unexported fields
}

StatisticsList is a wrapper for list of Statistics

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL