So implementieren Sie Ping in Golang

PHPz
Freigeben: 2023-04-25 14:03:55
Original
1616 Leute haben es durchsucht

golang implementiert Ping

Ping ist ein Tool zum Testen von Netzwerkverbindungen. Es wird verwendet, um die Konnektivität von Computernetzwerken zu testen. Der Ping-Befehl kann testen, ob der Zielhost online und erreichbar ist und wie hoch die Kommunikationsverzögerung ist. In diesem Artikel wird erläutert, wie Sie das Ping-Tool mithilfe der Programmiersprache Golang implementieren.

1. Was ist Ping? Ping ist ein unverzichtbares Tool für Programmierer und Systemadministratoren zur Fehlerbehebung und Fehlerbehebung im Netzwerk. Ping ist die Abkürzung für Packet Internet Groper und dient dazu, die Konnektivität der Netzwerkverbindung zwischen zwei Hosts zu testen. Der Ping-Befehl ist einer der grundlegendsten Netzwerkdienste im Internet. Er überprüft die Echtzeit und Zuverlässigkeit der Verbindung, indem er ICMP-Pakete an den Zielhost sendet und die Antwortzeit misst.

2. Wie Ping funktioniert

Das Prinzip von Ping besteht darin, den „Echo Request“-Befehl des Internet Control Message Protocol (ICMP) zu verwenden, um nach dem Empfang des Datenpakets ein spezielles Datenpaket an den Zielhost zu senden Der Host sendet automatisch ein „Echo-Antwort“-Paket an den Absender zurück, sodass der Absender die Antwortzeit und Netzwerklatenz des Zielhosts berechnen kann, indem er die Umlaufzeit des Pakets misst.

3. Ping implementieren

Um Ping zu implementieren, müssen Sie die folgenden 3 Schritte ausführen:

1. ICMP-Datenpakete erstellen

1. ICMP-Datenpaket erstellen

Zuerst müssen wir ein ICMP-Paket erstellen. Gemäß dem ICMP-Format können wir die Strukturen und Funktionen des mit der Go-Sprache gelieferten Pakets „icmp“ verwenden, um ein ICMP-Datenpaket zu erstellen. icmp.Message und icmp.Echo geben den Pakettyp und die typbezogenen Daten an, und icmp.Marshal ruft die von uns erstellten ICMP-Daten ab. Wir können eine PingMsg wie folgt definieren:

type PingMsg struct{

icmpMessage icmp.Message
bytes []byte
Nach dem Login kopieren

}

func newEchoPingMessage(id, seq int) (*PingMsg, error){

bytes := make([]byte, 32)
Nach dem Login kopieren

//Füllen Sie den ICMP-Paketinhalt

for i, _ := range bytes {
    bytes[i] = 'a' + byte(i%26)
}
icmpMessage := icmp.Message{
    Type: ipv4.ICMPTypeEcho, // ICMP类型
    Code: 0, // ICMP代码,置为0
    Checksum: 0, // 校验和,暂时置为0
    Body: &icmp.Echo{
        ID: id,
        Seq: seq,
        Data: bytes,
    },
}
Nach dem Login kopieren

/ / ICMP-Pakete serialisieren

b, err := icmpMessage.Marshal(nil)
if err != nil {
    return nil, err
}
return &PingMsg{
    bytes: b,
    icmpMessage: icmpMessage,
}, nil
Nach dem Login kopieren

}

2. ICMP-Pakete senden

Als nächstes müssen wir die vom Netzpaket bereitgestellte Conn-Schnittstelle verwenden, um die erstellten ICMP-Pakete zu senden. Wir können net.Dial("ip4:icmp", Destination) verwenden, um eine ICMP-Verbindung herzustellen, Conn.Write(b []byte) verwenden, um Datenpakete an den Zielhost zu senden, und die Funktion time.NewTicker verwenden, um das zu steuern Sendezeitintervall.

func ping(addr string) error{

conn, err := net.Dial("ip4:icmp", addr)
if err != nil {
    return err
}
defer conn.Close()
pingMsg, err := newEchoPingMessage(os.Getpid()&0xffff, 1)
if err != nil {
    return err
}
timeout := 5 * time.Second // 超时时间
ticker := time.NewTicker(time.Second) //设置1秒钟的时间间隔
defer ticker.Stop()
for {
    select {
    case <- ticker.C: // 每1秒钟发送一次ICMP数据包
        if _, err = conn.Write(pingMsg.bytes); err != nil {
            return err
        }
    case <- time.After(timeout): // 超时时间到了,抛出错误
        return errors.New("request timeout")
    }
}
Nach dem Login kopieren

}

3. Die vom ICMP-Paket zurückgegebenen Antwortinformationen analysieren

Zuletzt müssen wir die Antwortinformationen des Hosts analysieren, indem wir das zurückgegebene ICMP-Paket lesen. Wir verwenden auch die vom Net-Paket bereitgestellte Conn-Schnittstelle, um das zurückgegebene Datenpaket zu lesen, verwenden icmp.ParseMessage, um das Datenpaket zu analysieren, und erhalten die Antwortinformationen über icmp.Message.Body.(*icmp.EchoReply). CFunc-Empfangsfehler (Con NET.CONN) {

Rreeee

}

4. Vollständige Beispiele

Vollständiger Code wie folgt:

Package Main

import (

Rreeee

)

Type Pingmsg Strut {

Rreeee

}

func newEchoPingMessage(id, seq int) (*PingMsg, Fehler){

for {
    b := make([]byte, 512)
    conn.SetReadDeadline(time.Now().Add(time.Second)) // 设置超时时间
    if n, err := conn.Read(b); err != nil {
        if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
            continue
        }
        return err
    } else {
        recvMsg, err := icmp.ParseMessage(ipv4.ICMPTypeEchoReply, b[:n])
        if err != nil {
            return err
        }
        switch recvMsg.Type {
        case ipv4.ICMPTypeEchoReply:
            echoReply, _ := recvMsg.Body.(*icmp.EchoReply)
            log.Printf("ping %d bytes from %s: icmp_seq=%d time=%dms", len(echoReply.Data), conn.RemoteAddr().String(), echoReply.Seq, time.Since(time.Unix(0, echoReply.ArrivalTime().Nanoseconds())).Nanoseconds())
        default:
            log.Printf("unsupported ICMP message type %v (%v)", recvMsg.Type, recvMsg.Code)
        }
    }
}
Nach dem Login kopieren

}

func ping(addr string) Fehler{

"errors"
"fmt"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"log"
"net"
"os"
"time"
Nach dem Login kopieren

}

funcempfangenPing(conn net.Conn) Fehler{

icmpMessage icmp.Message
bytes       []byte
Nach dem Login kopieren

}

func main(){

bytes := make([]byte, 32)
for i, _ := range bytes {
    bytes[i] = 'a' + byte(i%26)
}
icmpMessage := icmp.Message{
    Type: ipv4.ICMPTypeEcho,
    Code: 0,
    Checksum: 0,
    Body: &icmp.Echo{
        ID: id,
        Seq: seq,
        Data: bytes,
    },
}
b, err := icmpMessage.Marshal(nil)
if err != nil {
    return nil, err
}
return &PingMsg{
    bytes: b,
    icmpMessage: icmpMessage,
}, nil
Nach dem Login kopieren

}

Wenn dieser Code ausgeführt wird, werden ICMP-Pakete kontinuierlich an den Zielhost gesendet, bis der Host eine Zeitüberschreitung erfährt oder eine Antwort erhält. Immer wenn ein Antwortpaket empfangen wird, gibt das Programm die folgende Information aus:

ping 32 bytes from 120.92.6.25: icmp_seq=0 time=29ms

Dies bedeutet, dass das Antwortpaket erfolgreich empfangen wurde und die Roundtrip-Zeit angezeigt wird . Zeit). Der Prozess der Ping-Implementierung ist sehr einfach, ermöglicht uns jedoch ein besseres Verständnis der Prinzipien der Netzwerkkommunikation.

Das obige ist der detaillierte Inhalt vonSo implementieren Sie Ping in Golang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage