This is a creation in Article, where the information may have evolved or changed.
A monitoring project has a need to detect a batch of domain names, including, packet loss rate, HTTP response time, the detection frequency is about 2min a period of time. There are about hundreds of domain names here, maybe thousands later. Because it is the dispatch and agent written by Golang, it is an interesting problem to detect the packet loss rate here. Since there is no easy-to-use library package that supports batch ping at this time, I have implemented one myself with reference to the implementation of others.
This article is still in the continuous update changes, please go to the original address http://dmwan.cc, git address: https://github.com/caucy/batch_ping
At first I didn't quite understand the ICMP protocol, and my idea was that there were several implementations.
The first is the simplest, and the way most monitoring agents are used: subprocess. One drawback of this approach is that each task will fork a process, one that consumes resources, and the second is too slow;
The second way, I think so, Golang has ICMP packet, can support send and recive, I directly from the association to send and receive, each process and subprocess like, first post, etc. It then sets up a pool of pools so that concurrency can be controlled. However, too young too ...
ICMP specific protocol not much to say, own Baidu, the main note under the ID field and the SEQ field (big-endian and small-endian is actually a field) on the line! Here are a few points to focus on.
The second approach does not work, mainly because of several reasons:
1, ICMP is the IP layer, TCP/UDP under the Protocol, no connection, this most people know;
2,ICMP is sent and received via the original socket, which requires root access. So library start requires authorization
3, the original socket listen, receive the time, is how to distinguish which process is issued, which process should receive? This is the key, the socket at the time of receiving, is the kernel direct forwarding, all ping their own machine package, can receive. What do you mean? own process, need to pass the ID (own process number) to mark this is sent out by themselves, the time of collection, grep off those who do not send the package.
4, the process how to distinguish between the order of sending and receiving, that is, I was the first few bags lost? This can be done according to Seq.
So what are we supposed to do? Actually know the above points on the idea is clear, to avoid the package does not belong to their own, pay attention to send and receive order, OK. The main implementation is to put all the domain name or IP into the IP after parsing into a map, a co-process, send ICMP, a co-receive ICMP, a tick control interval, a tick control the overall timeout. Finally, provide the next callback interface on OK.
Here is an example invocation:
Package Mainimport ( "batch_ping/ping" "Time" "FMT" "GOLANG.ORG/X/NET/ICMP") func main () { ipslice: = [] String{} ipslice = Append (Ipslice, "122.228.74.183") ipslice = Append (Ipslice, "wwww.baidu.com") Ipslice = append (Ipslice, "baidu.com") Ipslice = Append (Ipslice, "121.42.9.142") ipslice = append (Ipslice, "121.42.9.141") ipslice = Append (Ipslice, "121.42.9.144") ipslice = append (Ipslice, " 121.42.9.145 ") ipslice = append (Ipslice," 121.42.9.146 ") ipslice = Append (Ipslice, "121.42.9.147") ipslice = append (Ipslice, "121.42.9.148") ipslice = Append (Ipslice, "121.42.9.149") ipslice = append (Ipslice, "121.42.9.150 ") bp, err: = Ping. Newbatchpinger (Ipslice, 4, time. Second*1, time. Second*10, True) if err! = Nil { fmt. PRINTLN (Err) } bp. Onrecv = func (pkt *icmp. Echo, srcaddr string) { fmt. Printf ("Recv icmp_id=%d, icmp_seq=%d, srcaddr%v\n", pkt.id, PKT. Seq, srcaddr) } bp. OnFinish = func (Stmap map[string]*ping. Statistics) { for IP, st: = Range stmap{ fmt. Printf ("\ n---%s ping statistics---\ n", St. ADDR) fmt. Printf ("IP%s,%d packets transmitted,%d packets received,%v%% packet loss\n",ip, st. Packetssent, St. Packetsrecv, St. Packetloss) fmt. Printf ("Round-trip Min/avg/max/stddev =%v/%v/%v/%v\n", st. Minrtt, St. Avgrtt, St. Maxrtt, St. STDDEVRTT)         }    }    BP . Run ()}
Can do, can also support the next IPv6 and so on. If you feel the use of a star, thank you.