checkSum的计算

Posted 我要出家当道士

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了checkSum的计算相关的知识,希望对你有一定的参考价值。

目录

1、Introduction

 2、CheckSum Function(GO)

3、demo(GO)


1、Introduction

        下面主要介绍IP协议与UDP协议中校验和的计算(TCP与UDP类似),主要是自己记录一下,以后可以快速使用。传输层的以 UDP 为例。

        IP与UDP的校验和算法是一样的,都遵循 RFC1071。唯一的不同在于 IP 校验和的范围只包含 IP 头部,而 UDP 则包含 伪头部,UDP 头部 和 数据部分。UDP及其伪头部如下图所示。

 2、CheckSum Function(GO)

func checksum(data []byte) uint16 {
	csum := uint32(0)
	length := len(data) - 1
	for i := 0; i < length; i += 2 {
		csum += uint32(data[i]) << 8
		csum += uint32(data[i+1])
	}
	if len(data)%2 == 1 {
		csum += uint32(data[length]) << 8
	}
	for csum > 0xffff {
		csum = (csum >> 16) + (csum & 0xffff)
	}
	return ^uint16(csum)
}

3、demo(GO)

package main

import (
	"golang.org/x/sys/unix"
	"log"
	"net"
)

func checksum(data []byte) uint16 {
	csum := uint32(0)
	length := len(data) - 1
	for i := 0; i < length; i += 2 {
		// For our test packet, doing this manually is about 25% faster
		// (740 ns vs. 1000ns) than doing it by calling binary.BigEndian.Uint16.
		csum += uint32(data[i]) << 8
		csum += uint32(data[i+1])
	}
	if len(data)%2 == 1 {
		csum += uint32(data[length]) << 8
	}
	for csum > 0xffff {
		csum = (csum >> 16) + (csum & 0xffff)
	}
	return ^uint16(csum)
}

func rawSocket(ifaceName string) (fd int, err error) {
	protol := (unix.ETH_P_ALL<<8)&0xff00 | unix.ETH_P_ALL>>8
	fd, err = unix.Socket(unix.AF_PACKET, unix.SOCK_RAW, int(protol))
	if err != nil {
		return -1, err
	}
	ifIndex := 0
	if ifaceName != "" {
		iface, err := net.InterfaceByName(ifaceName)
		if err != nil {
			return -1, err
		}
		ifIndex = iface.Index
	}
	s := &unix.SockaddrLinklayer{
		Protocol: uint16(protol),
		Ifindex:  ifIndex,
	}
	err = unix.Bind(fd, s)
	return fd, err
}

var buff = []byte{0,12,41,222,152,91,0,12,41,222,152,91,8,0,69,0,0,38,159,34,64,0,64,17,0,0,192,168,2,201,192,168,2,201,
	29,50,29,49,0,18,0,0,1,1,1,1,1,1,1,1,1,1}

func main(){
	fd, _ := rawSocket("ens33")
	// ip
	cs := checksum(buff[14:34])
	buff[24] = byte(cs >> 8)
	buff[25] = byte(cs & 0xff)
	// udp
	ud := make([]byte, 12 + 8 + 10)
	copy(ud[:4], buff[26:30])
	copy(ud[4:8], buff[30:34])
	ud[8] = 0
	ud[9] = 17
	ud[10] = 0
	ud[11] = 18
	copy(ud[12:], buff[34:])
	ucs := checksum(ud)
	buff[40] = byte(ucs >> 8)
	buff[41] = byte(ucs & 0xff)
	log.Print(buff)
	unix.Write(fd, buff)
}

以上是关于checkSum的计算的主要内容,如果未能解决你的问题,请参考以下文章

checksum是啥意思

innodb 计算checksum

checkSum的计算

我如何使用此函数来计算CHECKSUM

如何计算UDP/TCP检验和checksum

Oracle 日志文件内的checksum计算