golang에서 ping을 구현하는 방법

PHPz
풀어 주다: 2023-04-25 14:03:55
원래의
1604명이 탐색했습니다.

golang은 ping을 구현합니다

Ping은 네트워크 연결을 테스트하는 도구입니다. 컴퓨터 네트워크의 연결을 테스트하는 데 사용됩니다. Ping 명령은 대상 호스트가 온라인인지, 액세스 가능한지, 통신 지연이 있는지 테스트할 수 있습니다. 이 기사에서는 golang 프로그래밍 언어를 사용하여 ping 도구를 구현하는 방법을 소개합니다.

1. Ping이란

Ping은 프로그래머와 시스템 관리자가 네트워크 디버깅 및 문제 해결을 수행하는 데 필수적인 도구입니다. Ping은 Packet Internet Groper의 약어이며 해당 기능은 두 호스트 간의 네트워크 연결 연결을 테스트하는 것입니다. Ping 명령은 인터넷에서 가장 기본적인 네트워크 서비스 중 하나이며 ICMP 패킷을 대상 호스트에 보내고 응답 시간을 측정하여 연결의 실시간 및 신뢰성을 확인합니다.

2. Ping 작동 방식

Ping의 원리는 대상 호스트가 이 데이터 패킷을 받은 후 ICMP(Internet Control Message Protocol)의 "에코 요청" 명령을 사용하여 대상 호스트에 보내는 것입니다. , 발신자가 패킷의 왕복 시간을 측정하여 대상 호스트의 응답 시간과 네트워크 대기 시간을 계산할 수 있도록 "에코 응답" 패킷을 발신자에게 자동으로 반환합니다.

3. ping 구현

ping을 구현하려면 다음 3단계를 완료해야 합니다.

1. ICMP 데이터 패킷 구성
2. ICMP 데이터 패킷에서 반환된 응답 정보 구문 분석 1. ICMP 데이터 패킷 구성

먼저 ICMP 패킷을 구성해야 합니다. ICMP 형식에 따르면 Go 언어와 함께 제공되는 "icmp" 패키지에서 제공하는 구조와 기능을 사용하여 ICMP 데이터 패킷을 구성할 수 있습니다. icmp.Message 및 icmp.Echo는 패킷 유형 및 유형 관련 데이터를 지정하고 icmp.Marshal은 우리가 구성한 ICMP 데이터를 검색합니다. PingMsg를 다음과 같이 정의할 수 있습니다:

type PingMsg struct{

icmpMessage icmp.Message
bytes []byte
로그인 후 복사
}

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

bytes := make([]byte, 32)
로그인 후 복사
//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,
    },
}
로그인 후 복사
/ / ICMP 패킷 직렬화

b, err := icmpMessage.Marshal(nil)
if err != nil {
    return nil, err
}
return &PingMsg{
    bytes: b,
    icmpMessage: icmpMessage,
}, nil
로그인 후 복사
}

2. ICMP 패킷 보내기

다음으로 구성된 ICMP 패킷을 보내기 위해 net 패키지에서 제공하는 Conn 인터페이스를 사용해야 합니다. net.Dial("ip4:icmp", Destination)을 사용하여 ICMP 연결을 설정하고, Conn.Write(b []byte)를 사용하여 대상 호스트에 데이터 패킷을 보내고, time.NewTicker 함수를 사용하여 제어할 수 있습니다. 보내는 시간 간격.

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")
    }
}
로그인 후 복사
}

3. ICMP 패킷에서 반환된 응답 정보를 구문 분석합니다

마지막으로 반환된 ICMP 패킷을 읽어 호스트의 응답 정보를 구문 분석해야 합니다. 또한 net 패키지에서 제공하는 Conn 인터페이스를 사용하여 반환된 데이터 패킷을 읽고, icmp.ParseMessage를 사용하여 데이터 패킷을 구문 분석하고, icmp.Message.Body.(*icmp.EchoReply)를 통해 응답 정보를 얻습니다. CFunc 수신(Con NET.CONN) 오류 {

Rreeee

}

4. 전체 예제

전체 코드는 다음과 같습니다.

Package Main

import(

Rreeee

)

Pingmsg Strut {

Rreeee

}

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

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)
        }
    }
}
로그인 후 복사
}

func ping(addr string) error{

"errors"
"fmt"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"log"
"net"
"os"
"time"
로그인 후 복사
}

func receivePing(conn net.Conn) error{

icmpMessage icmp.Message
bytes       []byte
로그인 후 복사
}

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
로그인 후 복사
}

이 코드가 실행되면 호스트가 시간 초과되거나 응답을 받을 때까지 ICMP 패킷이 대상 호스트로 계속 전송됩니다. 응답 패킷이 수신될 때마다 프로그램은 다음 정보를 출력합니다.

120.92.6.25에서 32바이트를 ping: icmp_seq=0 time=29ms

이는 응답 패킷이 성공적으로 수신되고 왕복 시간이 표시된다는 의미입니다. . 시간). Ping을 구현하는 과정은 매우 간단하지만 이를 통해 네트워크 통신의 원리를 더 잘 이해할 수 있습니다.

위 내용은 golang에서 ping을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿