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 데이터 패킷 구성
icmpMessage icmp.Message bytes []byte
bytes := make([]byte, 32)
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, }, }
b, err := icmpMessage.Marshal(nil) if err != nil { return nil, err } return &PingMsg{ bytes: b, icmpMessage: icmpMessage, }, nil
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") } }
Rreeee
} 4. 전체 예제 전체 코드는 다음과 같습니다. Package Mainimport(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) } } }
"errors" "fmt" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "log" "net" "os" "time"
icmpMessage icmp.Message bytes []byte
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
위 내용은 golang에서 ping을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!