熟悉报文结构

ICMP校验和算法:
- 报文内容,相邻两个字节拼接到一起组成一个16bit数,将这些数累加求和
- 若长度为奇数,则将剩余一个字节,也累加求和
- 得出总和之后,将和值的高16位与低16位不断求和,直到高16位为0
- 以上三步得出结果后,取反,即为验证和

我们选取实现其中的
先实现命令行部分
var (
timeout int64
size int
count int
)
func getCommandArgs() {
//通过flag.来读命令行的参数
flag.Int64Var(&timeout, "w", 1000, "请求超时时长,单位毫秒")
flag.IntVar(&size, "l", 32, "请求发送缓冲区大小,单位字节")
flag.IntVar(&count, "n", 4, "发送请求数")
flag.Parse()
}
func main() {
getCommandArgs()
fmt.Println(timeout, size, count)
}

测试显示,可以成功拿到命令行的参数

定义ICMP报文格式
type ICMP struct{
Type uint8
Code uint8
Checksum uint16
ID uint16
SequenceNum uint16
}
全部代码加注释
package main
import (
"bytes"
"encoding/binary"
"flag"
"fmt"
"log"
"net"
"os"
"time"
)
// 定义全局变量
var (
timeout int64 // 请求超时时长,单位毫秒
size int // 请求发送缓冲区大小,单位字节
count int // 发送请求数
typ uint8 = 8 // ICMP请求类型
code uint8 = 0 // ICMP请求代码
)
// ICMP结构体定义ICMP请求的数据结构
type ICMP struct {
Type uint8
Code uint8
Checksum uint16
ID uint16
SequenceNum uint16
}
func main() {
getCommandArgs() // 获取命令行参数
// 取出最后一个参数,即目标IP地址
desIp := os.Args[len(os.Args)-1]
// 建立ICMP连接
conn, err := net.DialTimeout("ip:icmp", desIp, time.Duration(timeout)*time.Millisecond)
if err != nil {
// 如果连接建立失败,直接返回
log.Fatal(err)
return
}
defer conn.Close()
// 打印Ping信息
fmt.Printf(" 正在Ping %s [%s] 具有 %d 字节的数据:\n", desIp, conn.RemoteAddr(), size)
// 发送ICMP请求并接收响应
for i :=

最低0.47元/天 解锁文章
1367

被折叠的 条评论
为什么被折叠?



