Go語言實現ping命令

2021-09-20 01:25:07 字數 3395 閱讀 5607

ping是使用icmp協議

icmp協議的組成:type(8bits) + code(8bits) + 校驗碼(checksum,8bits) + id(16bits) + 序號(sequence,16bits) + 資料

這些組成部分的含義:

1)type icmp的型別,標識生成的錯誤報文

2)code 進一步劃分icmp的型別,該欄位用來查詢產生的原因;例如,icmp的目標不可達型別可以把這個位設為1至15等來表示不同的意思。

3)checksum 校驗碼部分,這個字段包含從icmp報頭和資料部分計算得來的,用於檢查錯誤的,其中此校驗碼欄位的值視為0.

4)id 這個字段包含了id值,在echo reply型別的訊息中要返回這個字段。

5)sequence 這個字段包含乙個序號

ping命令的實現是使用icmp中型別值為8(reply)和0(request)

現在開始編寫**:

一、解析引數

var (

icmp icmp

laddr = net.ipaddr

//raddr, _ = net.resolveipaddr("ip", os.args[1])

num int

timeout int64

size int

stop bool

)func parseargs()

二、定義icmp結構體

type icmp struct
三、為icmp變數設定值

//icmp頭部填充

icmp.type = 8

icmp.code = 0

icmp.checksum = 0

icmp.identifier = 1

icmp.sequencenum = 1

四、計算icmp校驗和

這邊講解下校驗和的計算,icmp的校驗和ip的校驗不同,icmp的校驗是校驗icmp頭部和資料內容,icmp校驗和計算過程如下:

1)將icmp頭部內容中的校驗內容(checksum)的值設為0

2)將拼接好(type+code+checksum+id+seq+傳輸data)的icmp包按type開始每兩個位元組一組(其中checksum的兩個位元組都看成0),進行加和處理,如果位元組個數為奇數個,則直接加上這個位元組內容。說明:這個加和過程的內容放在乙個4位元組上,如果溢位4位元組,則將溢位的直接拋棄

3)將高16位與低16位內容加和,直到高16為0

4)將步驟三得出的結果取反,得到的結果就是icmp校驗和的值

驗證校驗和的方式也是一樣,驗證時先計算驗證和,然後和驗證和中內容進行比較是否一樣

func checksum(data byte) uint16 

if length == 1

sum = uint16(sum >> 16) + uint16(sum)

sum = uint16(sum >> 16) + uint16(sum)

return uint16(^sum)

}

五、傳送icmp包

六、列印結果

package main

import (

"bytes"

"encoding/binary"

"flag"

"fmt"

"log"

"net"

"os"

"time"

"math"

)type icmp struct

var (

icmp icmp

laddr = net.ipaddr

num int

timeout int64

size int

stop bool

)func main()

desip := args[len(args) - 1]

conn, err := net.dialtimeout("ip:icmp", desip, time.duration(timeout) * time.millisecond)

if err != nil

defer conn.close()

//icmp頭部填充

icmp.type = 8

icmp.code = 0

icmp.checksum = 0

icmp.identifier = 1

icmp.sequencenum = 1

fmt.printf("\n正在 ping %s 具有 %d 位元組的資料:\n", desip, size)

var buffer bytes.buffer

binary.write(&buffer, binary.bigendian, icmp) // 以大端模式寫入

data := make(byte, size) //

buffer.write(data)

data = buffer.bytes()

var successtimes int // 成功次數

var failtimes int // 失敗次數

var mintime int = int(math.maxint32)

var maxtime int

var totaltime int

for i := 0;i < num;i++

buf := make(byte, 65535)

n, err = conn.read(buf)

if err != nil

et := int(time.since(t1) / 1000000)

if mintime > et

if maxtime 1

if length == 1

// checksum的值是16位,計算是將高16位加低16位,得到的結果進行重複以該方式進行計算,直到高16位為0

/*sum的最大情況是:ffffffff

第一次高16位+低16位:ffff + ffff = 1fffe

第二次高16位+低16位:0001 + fffe = ffff

即推出乙個結論,只要第一次高16位+低16位的結果,再進行之前的計算結果用到高16位+低16位,即可處理溢位情況

*/sum = uint32(sum >> 16) + uint32(sum)

sum = uint32(sum >> 16) + uint32(sum)

return uint16(^sum)

}func parseargs()

func usage()

}

參考文章:

1)2)

3)4)

C語言實現ping命令(一)

ping命令使用到了網路中的icmp協議 關於icmp介紹看這裡 網路位址資訊 struct sockaddr in struct in addr struct in addr define in addr t uint32 t 無符號整型32位 還可以使用以下結構體 struct sockaddr...

Go語言實現Valid Parentheses

write a function called that takes a string of parentheses,and determines if the order of the parentheses is valid.the function should return true if ...

如何使用Go語言實現遠端執行命令

前言 遠端執行命令有什麼用?為什麼要遠端執行命令wgrgtkdtxn?如果你只有2,3臺伺服器需要管理的時候,遠端執行命令確實沒有沒多大作用,你可以登入到每台伺服器上去完成各種操作。當你的伺服器大於3臺的時候,遠端執行的命令的方式就可以大大提高你的生產力了。如果你有乙個可以遠端執行命令的工具,那麼就...