Maison > développement back-end > Golang > le corps du texte

Comment implémenter le ping dans Golang

PHPz
Libérer: 2023-04-25 14:03:55
original
1604 Les gens l'ont consulté

golang implémente ping

Ping est un outil pour tester les connexions réseau. Il est utilisé pour tester la connectivité des réseaux informatiques. La commande Ping peut tester si l'hôte cible est en ligne, accessible et le délai de communication. Cet article explique comment implémenter l'outil ping à l'aide du langage de programmation Golang.

1. Qu'est-ce que Ping

Ping est un outil essentiel permettant aux programmeurs et aux administrateurs système d'effectuer le débogage et le dépannage du réseau. Ping est l'abréviation de Packet Internet Groper, et sa fonction est de tester la connectivité de la connexion réseau entre deux hôtes. La commande Ping est l'un des services réseau les plus basiques sur Internet. Elle vérifie le temps réel et la fiabilité de la connexion en envoyant des paquets ICMP à l'hôte cible et en mesurant le temps de réponse.

2. Comment fonctionne Ping

Le principe de Ping est d'utiliser la commande "echo request" du protocole ICMP (Internet Control Message Protocol) pour envoyer un paquet de données spécial à l'hôte cible. L'hôte renvoie automatiquement un paquet de « réponse d'écho » à l'expéditeur afin que celui-ci puisse calculer le temps de réponse de l'hôte cible et la latence du réseau en mesurant le temps d'aller-retour du paquet.

3. Implémentation de ping

Pour implémenter ping, vous devez effectuer les 3 étapes suivantes :

1. Construire des paquets de données ICMP
2. Envoyer des paquets de données ICMP
3. Analyser les informations de réponse renvoyées par les paquets de données ICMP. 1. Construire un paquet de données ICMP

Tout d'abord, nous devons construire un paquet ICMP. Selon le format ICMP, nous pouvons utiliser les structures et fonctions fournies par le package « icmp » fourni avec le langage Go pour construire un paquet de données ICMP. icmp.Message et icmp.Echo spécifient le type de paquet et les données liées au type, et icmp.Marshal récupère les données ICMP que nous avons construites. Nous pouvons définir un PingMsg comme suit :

type PingMsg struct{

icmpMessage icmp.Message
bytes []byte
Copier après la connexion

}

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

bytes := make([]byte, 32)
Copier après la connexion

//Remplir le contenu du paquet ICMP

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,
    },
}
Copier après la connexion

/ / Sérialiser les paquets ICMP

b, err := icmpMessage.Marshal(nil)
if err != nil {
    return nil, err
}
return &PingMsg{
    bytes: b,
    icmpMessage: icmpMessage,
}, nil
Copier après la connexion

}

2. Envoyer des paquets ICMP

Ensuite, nous devons utiliser l'interface Conn fournie par le package net pour envoyer les paquets ICMP construits. Nous pouvons utiliser net.Dial("ip4:icmp", destination) pour établir une connexion ICMP, utiliser Conn.Write(b []byte) pour envoyer des paquets de données à l'hôte cible et utiliser la fonction time.NewTicker pour contrôler le intervalle de temps d'envoi.

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")
    }
}
Copier après la connexion

}

3. Analyser les informations de réponse renvoyées par le paquet ICMP

Enfin, nous devons analyser les informations de réponse de l'hôte en lisant le paquet ICMP renvoyé. Nous utilisons également l'interface Conn fournie par le package net pour lire le paquet de données renvoyé, utilisons icmp.ParseMessage pour analyser le paquet de données et obtenons les informations de réponse via icmp.Message.Body.(*icmp.EchoReply). Erreur de réception CFunc (Con NET.CONN) {

Rreeee

}

4. Exemples complets

Code complet comme suit :

Package Main

import (

Rreeee

)

Type Pingmsg Strut {

Rreeee

}

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

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)
        }
    }
}
Copier après la connexion

}

func ping(addr string) error{

"errors"
"fmt"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"log"
"net"
"os"
"time"
Copier après la connexion

}

func containPing(conn net.Conn) error{

icmpMessage icmp.Message
bytes       []byte
Copier après la connexion

}

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
Copier après la connexion

}

Lorsque ce code est exécuté, les paquets ICMP seront envoyés en continu à l'hôte cible jusqu'à ce que l'hôte expire ou reçoive une réponse. Chaque fois qu'un paquet de réponse est reçu, le programme affichera les informations suivantes :

ping 32 octets de 120.92.6.25 : icmp_seq=0 time=29ms

Cela signifie que le paquet de réponse est reçu avec succès et que le temps aller-retour est affiché . temps). Le processus de mise en œuvre de Ping est très simple, mais il permet de mieux comprendre les principes de la communication réseau.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal