udp校验和计算及伪首部

本文详细介绍了UDP首部校验和的计算过程,包括参与校验的数据和伪首部的作用。通过实例展示了如何计算和验证校验和,确保数据在传输过程中的准确性。

UDP中的伪首部是干什么用得到?

 

 

UDP首部校验和计算: 

对于TCP和UDP的数据报,其头部也包含16位的校验和,校验算法与IPv4分组头完全一致,但参与校验的数据不同。

这时校验和不仅包含整个TCP/UDP数据报,还覆盖了一个虚头部(伪首部)

 

校验和计算

u_int16_t in_cksum (u_int16_t * addr, int len)
{
	int     nleft = len;
	u_int32_t sum = 0;
	u_int16_t *w = addr;
	u_int16_t answer = 0;

	/*
	* Our algorithm is simple, using a 32 bit accumulator (sum), we add
	* sequential 16 bit words to it, and at the end, fold back all the
	* carry bits from the top 16 bits into the lower 16 bits.
	*/
	while (nleft > 1) {
		sum += *w++;
		nleft -= 2;
	}
	/* mop up an odd byte, if necessary */
	if (nleft == 1) {
		* (unsigned char *) (&answer) = * (unsigned char *) w;
		sum += answer;
	}

	/* add back carry outs from top 16 bits to low 16 bits */
	sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
	sum += (sum >> 16);     /* add carry */
	answer = ~sum;     /* truncate to 16 bits */
	return (answer);
}

==================不足偶数字节补0


45 00 00 2e----4表示ip版本号为ip第4版;5表示首部长度为5个32 bit字长,即为20字节;00 2e表示ip总长度为46字节,其中ip数据部分为26字节。 
be 55 00 00----be 55表示标识符;00 00表示3 bit标志及13 bit片偏移量; 
7a 11 51 ac----7a表示ttl值为122;11表示协议号为17的udp协议;51 ac表示16 bit首部检验和值; 
de b7 7e e3----表示32 bit 源ip地址为222.183.126.227 
c0 a8 12 7a----表示32 bit 目的ip地址为192.168.18.122
 

 

//不需要htons,详见rfc1071
picmp_hdr->icmp_chksum = checksum((unsigned short*)pSendBuf, sizeof (ICMPHeader) + nSendDataSize);

之后发送pSendBuf中的数据,长度为sizeof (ICMPHeader) + nSendDataSize;

char *pRecvBuf = new char[sizeof(ICMPHeader) + nSendDataSize];
当接收到数据报再对它进行校验和验证,假设接收到的icmp数据存在pRecvBuf中

ICMPHeader *picmp_hdr2 = (ICMPHeader*)pRecvBuf;

 //注意:验证数据的时候,不需要转化为主机字节序列,
 //因为校验和发送端是以网络字节序来计算的,接收到的字节序列已经是网络字节序
 //根据接收到的校验和进行验证

//不需要ntohs,详见rfc1071
//picmp_hdr2->checksum = ntohs(picmp_hdr2->checksum);

  1. unsigned short check_sum(unsigned short *a, int len)  
  2. {  
  3.     unsigned int sum = 0;  
  4.   
  5.     while (len > 1) {  
  6.         sum += *a++;  
  7.         len -= 2;  
  8.     }  
  9.   
  10.     if (len) {  
  11.         sum += *(unsigned char *)a;  
  12.     }  
  13.   
  14.     while (sum >> 16) {  
  15.         sum = (sum >> 16) + (sum & 0xffff);  
  16.     }  
  17.   
  18.     return (unsigned short)(~sum);  
  19. }  

==================检验和验证计算========================


首先,把检验和字段置为0。 
45 00 00 2e 
be 55 00 00 
7a 11 00 00<----检验和置为0 
de b7 7e e3 
c0 a8 12 7a 
其次,对整个首部中的每个16 bit进行二进制反码求和,

求和值为0x3_ae50,然后3+ae50=0xae53(这是根据源代码中算法 cksum = (cksum >> 16) + (cksum & 0xffff) 进行的 ) 
最后,ae53+51ac=ffff。因此判断ip首部在传输过程中没有发生任何差错。
 

<think> 我们正在讨论TCP校验和计算中的首部。根据引用[1]和引用[3],首部包含以下字段: - 32位源IP地址 - 32位目的IP地址 - 8位填充0(全0) - 8位协议(TCP的协议号是6) - 16位TCP长度(即TCP首部加上数据部分的长度,以字节为单位) 注意:首部并不是TCP数据报的实际首部,而是为了计算校验和而临时构造的。 计算TCP校验和的步骤如下: 1. 构造首部(12字节) 2. 将首部、TCP首部以及TCP数据部分组合起来,形成一个待校验的数据块。 3. 如果数据块的长度不是16位的整数倍,则在末尾填充0(填充内容不参与传输,仅用于校验和计算)。 4. 将数据块按16位(2字节)为一组进行分割,然后对这些16位字进行二进制反码求和。 5. 将得到的和再取反,即为校验和首部各字段的取值说明: 1. **源IP地址(32位)**:取自IP首部的源IP地址字段。 2. **目的IP地址(32位)**:取自IP首部的目的IP地址字段。 3. **填充(8位)**:设置为0。 4. **协议(8位)**:TCP的协议号是6(在IPv4中)。注意:虽然引用[1]提到首部有8位协议,但实际在IPv4中,这个字段就是IP首部中的协议字段的值。 5. **TCP长度(16位)**:指TCP首部加上数据部分的长度(以字节为单位)。注意:这个长度不包括首部,也不包括IP首部。 为什么需要首部首部的引入是为了确保数据报被正确送达(不仅送到正确的主机,还要送到正确的协议和正确的端口)。通过包含IP地址和协议字段,校验和能够检测出传送过程中IP地址被修改、协议类型被修改或者端口号被修改的错误。 注意:在计算校验和时,TCP首部中的校验和字段在计算过程中被置为0。 举例说明: 假设有一个TCP段,其源IP地址是192.168.1.2,目的IP地址是192.168.1.3,TCP首部长度20字节,数据部分长度为10字节(总共30字节)。那么首部的构造如下: - 源IP地址:192.168.1.2 -> 32位:0xC0A80102(十六进制) - 目的IP地址:192.168.1.3 -> 32位:0xC0A80103 - 填充+协议:8位填充0(0x00)和8位协议(0x06)组合成16位:0x0006 - TCP长度:30(0x001E) 因此,首部的12字节(按16位字排列)为: 0xC0A8, 0x0102, 0xC0A8, 0x0103, 0x0006, 0x001E 然后,将首部与TCP首部校验和字段设为0)以及数据部分一起,按16位字进行二进制反码求和,最后取反得到校验和。 引用[2]提到了硬件校验和的处理方式,但对于软件计算,我们通常需要包含首部。 注意:在IPv6中,首部的结构有所不同,包括源地址和目的地址都是128位,并且协议字段后面的长度字段是32位。 参考文献: [^1]: 首部包含32位源IP地址、32位目的IP地址、8位填充0,8位协议,16位TCP/UDP长度。 [^3]: UDP首部类似,但TCP首部的协议字段为6,UDP为17。 现在,我们来生成相关问题: </think> ### TCP校验和计算首部各字段详解 在TCP校验和计算中,首部(pseudo-header)是临时构造的数据结构,用于增强校验的可靠性。其组成格式及各字段含义如下(按TCP校验和规范): #### 首部结构(12字节) ``` 0 7 8 15 16 23 24 31 +--------+--------+--------+--------+ | 源IP地址 | [IPv4地址] +--------+--------+--------+--------+ | 目的IP地址 | [IPv4地址] +--------+--------+--------+--------+ | 填充0 | 协议号 | TCP长度 | [关键字段] +--------+--------+--------+--------+ ``` #### 各字段详解 1. **源IP地址(32位)** - **含义**:发送方的IPv4地址 - **取值**:直接从IP首部复制 - **作用**:确保数据包来自声明的源地址[^1] 2. **目的IP地址(32位)** - **含义**:接收方的IPv4地址 - **取值**:直接从IP首部复制 - **作用**:验证数据包是否发往本机[^1] 3. **填充0(8位)** - **取值**:固定为全0(`0x00`) - **作用**:对齐32位边界,无实际含义 4. **协议号(8位)** - **含义**:上层协议标识符 - **取值**:TCP固定为`6`(`0x06`) - **作用**:防止协议混淆(如TCP/UDP错传)[^1] 5. **TCP长度(16位)** - **含义**:TCP报文总长度(首部+数据) - **计算**:$$ \text{TCP长度} = \text{IP总长度} - \text{IP首部长度} \times 4 $$ - **校验范围**:需覆盖整个TCP报文段[^3] #### 校验和计算流程 1. **构造首部**:按上述格式填充各字段值 2. **组合校验数据**:首部 + TCP首部校验和字段置零)+ TCP数据 3. **二进制反码求和**:每16位为一组叠加计算 $$ \text{checksum} = \neg(\sum_{i=1}^{n} \text{word}_i) $$ 4. **填充结果**:将计算结果写入TCP首部校验和字段 #### 设计意义 首部的核心作用是建立**三层与四层的关联校验**: - 验证IP地址真实性(防地址欺骗) - 防止协议错传(TCP协议号=6) - 确保数据完整性(长度字段验证)[^1] - 弥补纯TCP校验无法检测IP层篡改的缺陷 > ⚠️ 注意:首部仅用于校验计算,不参与实际传输,接收方需用相同规则重构首部验证校验和。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

字正腔圆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值