tcp校验和

本文深入探讨了TCP伪首部的概念及其在计算校验和中的作用,详细解释了RFC793中规定的校验和计算方法,并通过实例演示了校验和的计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

伪首部(pseudo header),通常指TCP伪首部和UDP伪首部
TCP的校验和是必需的,而UDP的校验和是可选的
TCP校验是需要校验包头和数据的

//共12字节
typedef struct
{
    unsigned long saddr; //源IP地址
    unsigned long daddr; //目的IP地址
    unsigned char mbz; // mbz = must be zero, 用于填充对齐
    unsigned char protocal; //8位协议号
    unsigned short tcpl; //TCP包长度
}psdheader_t;

伪首部是一个虚拟的数据结构,仅仅是为计算校验和
接收方计算检验和错误,IP就丢弃收到的数据报

tcp

RFC 793的TCP校验和定义
The checksum field is the 16 bit one’s complement of the one’s complement sum of all 16-bit words in the header and text.
If a segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right
with zeros to form a 16-bit word for checksum purposes. The pad is not transmitted as part of the segment. While computing
the checksum, the checksum field itself is replaced with zeros

如果总长度为奇数个字节,则在最后增添一位都为0的字节
首先,把TCP报头中的校验和字段置为0
其次,用反码相加法累加所有的16位字
最后,对计算结果取反

详细计算方法见ip校验和:
http://blog.youkuaiyun.com/zhangxuechao_/article/details/50677220

举例

本地IP: 0xc0 0xa8 0x9f 0x01
对方IP: 0xc0 0xa8 0x9f 0x82
TCP字段: 0x04 0xc6 0x87 0x01 0x4b 0xd7 0x89 0x9f 0x4e 0x3b  0x90 0xae 0x50 0x18 0xff 0xff 0xeb 0x69 0x00 0x00

(0xc0a8 + 0x9f01 + 0xc0a8 + 0x9f82 + 0x0006 + 0x0017) + 0x04c6 + 0x8701 + 0x4bd7 + 0x899f + 0x4e3b + 0x90ae + 0x5018 
+ 0xffff + 0x0000 + 0x0000 + 0x6162 + 0x6300 = 0x7148f
0x0007 + 0x148f = 0x1496
~0x1496 = 0xeb69

注:tcpl指的是tcp包头和数据的总长度(网络字节序)

### Golang 中 TCP 校验和的实现 在 Golang 的标准库 `net` 和 `syscall` 中,提供了处理网络通信的功能,其中包括对 TCP 数据包的支持。然而,默认情况下,Go 并不会直接暴露底层的校验和计算逻辑给开发者,因为这些细节通常由操作系统或硬件自动完成。如果需要手动实现 TCP 校验和功能,则可以通过调用低级别的 socket API 或者使用第三方库。 以下是关于如何在 Golang 中实现 TCP 校验和的一个例子: #### 手动计算 TCP 校验和 TCP 校验和是一个基于伪头部(pseudo-header)、TCP 头部以及数据部分的简单求和算法。其核心步骤如下: 1. 构造伪头部。 2. 将伪头部、TCP 头部和数据拼接在一起。 3. 使用二进制补码方式逐字节累加并取反得到最终的校验和。 下面是具体的代码示例: ```go package main import ( "bytes" "encoding/binary" "fmt" ) // 计算校验和的核心方法 func calculateChecksum(data []byte) uint16 { sum := 0 for i := 0; i < len(data)-1; i += 2 { sum += int(uint16(data[i])<<8 | uint16(data[i+1])) } if len(data)%2 == 1 { sum += int(data[len(data)-1]) } for sum>>16 != 0 { sum = (sum >> 16) + (sum & 0xffff) } return ^uint16(sum) } // 创建伪头部结构体 type pseudoHeader struct { SrcIP [4]byte DstIP [4]byte Zero uint8 Proto uint8 Length uint16 } // 示例函数用于演示 TCP 校验和计算过程 func computeTCPChecksum(srcIP, dstIP string, payload []byte) uint16 { var srcAddr, dstAddr [4]byte copy(srcAddr[:], net.ParseIP(srcIP).To4()) copy(dstAddr[:], net.ParseIP(dstIP).To4()) pseudoHdr := pseudoHeader{ SrcIP: srcAddr, DstIP: dstAddr, Zero: 0, Proto: 6, // TCP 协议号为 6 Length: uint16(len(payload)), } buf := new(bytes.Buffer) binary.Write(buf, binary.BigEndian, pseudoHdr) buf.Write(payload) checksum := calculateChecksum(buf.Bytes()) return checksum } func main() { srcIP := "192.168.1.1" dstIP := "192.168.1.2" payload := []byte{0x01, 0x02, 0x03, 0x04} // 假设这是要发送的数据 checksum := computeTCPChecksum(srcIP, dstIP, payload) fmt.Printf("Computed Checksum: %v\n", checksum) } ``` 上述代码展示了如何构造伪头部,并将其与实际数据一起传递到校验和计算函数中[^1]。 #### 关于 HashiCorp 插件系统的扩展思考 虽然上面的例子主要关注的是 TCP 校验和的手动实现,但在某些场景下可能还需要考虑与其他框架集成的情况。例如,在使用 `hashicorp/go-plugin` 实现插件化架构时,可以利用类似的机制来验证消息完整性或者增强安全性[^2]。 #### 总结 通过以上分析可以看出,在 Golang 中尽管可以直接依赖操作系统的帮助来进行高效的网络传输管理,但如果确实存在特殊需求也可以自行编写相应的工具类辅助程序完成特定任务比如这里提到的 TCP 校验和运算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值