
用 Go 手写一个 Ping 工具
net 和 golang.org/x/net/icmp 包ping.go 的实现package main
import (
"fmt"
"net"
"os"
"time"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
)
const (
icmpTypeEchoRequest = 8
icmpTypeEchoReply = 0
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run ping.go <host>")
return
}
host := os.Args[1]
address, err := net.ResolveIPAddr("ip", host)
if err != nil {
fmt.Println("ResolveIPAddr failed:", err)
return
}
conn, err := net.DialIP("ip4:icmp", nil, address)
if err != nil {
fmt.Println("DialIP failed:", err)
return
}
defer conn.Close()
for i := 0; i < 4; i++ {
start := time.Now()
err = sendICMP(conn, address)
if err != nil {
fmt.Println("Send failed:", err)
return
}
err = receiveICMP(conn)
if err != nil {
fmt.Println("Receive failed:", err)
return
}
rtt := time.Since(start)
fmt.Printf("Reply from %s: bytes=32 time=%v\n", host, rtt)
time.Sleep(1 * time.Second)
}
}
func sendICMP(conn *net.IPConn, address *net.IPAddr) error {
msg := icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{Seq: 1, ID: 1, Data: []byte("HELLO")},
}
data, err := msg.Marshal(nil)
if err != nil {
return err
}
_, err = conn.WriteTo(data, address)
return err
}
func receiveICMP(conn *net.IPConn) error {
buf := make([]byte, 1500)
conn.SetReadDeadline(time.Now().Add(2 * time.Second))
_, _, err := conn.ReadFrom(buf)
return err
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。