142 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # go-ping
 | |
| [](https://pkg.go.dev/github.com/go-ping/ping)
 | |
| [](https://circleci.com/gh/go-ping/ping)
 | |
| 
 | |
| A simple but powerful ICMP echo (ping) library for Go, inspired by
 | |
| [go-fastping](https://github.com/tatsushid/go-fastping).
 | |
| 
 | |
| Here is a very simple example that sends and receives three packets:
 | |
| 
 | |
| ```go
 | |
| pinger, err := ping.NewPinger("www.google.com")
 | |
| if err != nil {
 | |
| 	panic(err)
 | |
| }
 | |
| pinger.Count = 3
 | |
| err = pinger.Run() // Blocks until finished.
 | |
| if err != nil {
 | |
| 	panic(err)
 | |
| }
 | |
| stats := pinger.Statistics() // get send/receive/duplicate/rtt stats
 | |
| ```
 | |
| 
 | |
| Here is an example that emulates the traditional UNIX ping command:
 | |
| 
 | |
| ```go
 | |
| pinger, err := ping.NewPinger("www.google.com")
 | |
| if err != nil {
 | |
| 	panic(err)
 | |
| }
 | |
| 
 | |
| // Listen for Ctrl-C.
 | |
| c := make(chan os.Signal, 1)
 | |
| signal.Notify(c, os.Interrupt)
 | |
| go func() {
 | |
| 	for _ = range c {
 | |
| 		pinger.Stop()
 | |
| 	}
 | |
| }()
 | |
| 
 | |
| pinger.OnRecv = func(pkt *ping.Packet) {
 | |
| 	fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v\n",
 | |
| 		pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt)
 | |
| }
 | |
| 
 | |
| pinger.OnDuplicateRecv = func(pkt *ping.Packet) {
 | |
| 	fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v ttl=%v (DUP!)\n",
 | |
| 		pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt, pkt.Ttl)
 | |
| }
 | |
| 
 | |
| pinger.OnFinish = func(stats *ping.Statistics) {
 | |
| 	fmt.Printf("\n--- %s ping statistics ---\n", stats.Addr)
 | |
| 	fmt.Printf("%d packets transmitted, %d packets received, %v%% packet loss\n",
 | |
| 		stats.PacketsSent, stats.PacketsRecv, stats.PacketLoss)
 | |
| 	fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n",
 | |
| 		stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt)
 | |
| }
 | |
| 
 | |
| fmt.Printf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr())
 | |
| err = pinger.Run()
 | |
| if err != nil {
 | |
| 	panic(err)
 | |
| }
 | |
| ```
 | |
| 
 | |
| 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
 | |
| unless a packet with that sequence number has already been received,
 | |
| in which case it calls the `OnDuplicateRecv` callback. When it's
 | |
| finished, it calls the `OnFinish` callback.
 | |
| 
 | |
| For a full ping example, see
 | |
| [cmd/ping/ping.go](https://github.com/go-ping/ping/blob/master/cmd/ping/ping.go).
 | |
| 
 | |
| ## Installation
 | |
| 
 | |
| ```
 | |
| go get -u github.com/go-ping/ping
 | |
| ```
 | |
| 
 | |
| To install the native Go ping executable:
 | |
| 
 | |
| ```bash
 | |
| go get -u github.com/go-ping/ping/...
 | |
| $GOPATH/bin/ping
 | |
| ```
 | |
| 
 | |
| ## Supported Operating Systems
 | |
| 
 | |
| ### Linux
 | |
| This library attempts to send an "unprivileged" ping via UDP. On Linux,
 | |
| this must be enabled with the following sysctl command:
 | |
| 
 | |
| ```
 | |
| sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"
 | |
| ```
 | |
| 
 | |
| If you do not wish to do this, you can call `pinger.SetPrivileged(true)`
 | |
| in your code and then use setcap on your binary to allow it to bind to
 | |
| raw sockets (or just run it as root):
 | |
| 
 | |
| ```
 | |
| setcap cap_net_raw=+ep /path/to/your/compiled/binary
 | |
| ```
 | |
| 
 | |
| See [this blog](https://sturmflut.github.io/linux/ubuntu/2015/01/17/unprivileged-icmp-sockets-on-linux/)
 | |
| and the Go [x/net/icmp](https://godoc.org/golang.org/x/net/icmp) package
 | |
| for more details.
 | |
| 
 | |
| ### Windows
 | |
| 
 | |
| You must use `pinger.SetPrivileged(true)`, otherwise you will receive
 | |
| the following error:
 | |
| 
 | |
| ```
 | |
| socket: The requested protocol has not been configured into the system, or no implementation for it exists.
 | |
| ```
 | |
| 
 | |
| Despite the method name, this should work without the need to elevate
 | |
| privileges and has been tested on Windows 10. Please note that accessing
 | |
| packet TTL values is not supported due to limitations in the Go
 | |
| x/net/ipv4 and x/net/ipv6 packages.
 | |
| 
 | |
| ### Plan 9 from Bell Labs
 | |
| 
 | |
| There is no support for Plan 9. This is because the entire `x/net/ipv4` 
 | |
| and `x/net/ipv6` packages are not implemented by the Go programming 
 | |
| language.
 | |
| 
 | |
| ## Maintainers and Getting Help:
 | |
| 
 | |
| This repo was originally in the personal account of
 | |
| [sparrc](https://github.com/sparrc), but is now maintained by the
 | |
| [go-ping organization](https://github.com/go-ping).
 | |
| 
 | |
| For support and help, you usually find us in the #go-ping channel of
 | |
| Gophers Slack. See https://invite.slack.golangbridge.org/ for an invite
 | |
| to the Gophers Slack org.
 | |
| 
 | |
| ## Contributing
 | |
| 
 | |
| Refer to [CONTRIBUTING.md](https://github.com/go-ping/ping/blob/master/CONTRIBUTING.md)
 |