365真正的官网-beat365体育登陆网址-365bet.com

— 怀旧经典 · 永恒记忆 —

TCP校验和(Checksum)的原理和实现

TCP校验和(Checksum)的原理和实现

概述

TCP校验和(Checksum)是一个端到端的校验和,由发送端计算,然后由接收端验证。其目的是为了发现TCP首部和数据在发送端到接收端之间发生的任何改动。如果接收方检测到校验和有差错,则TCP段会被直接丢弃。

TCP校验和覆盖TCP首部和TCP数据,而IP首部中的校验和只覆盖IP的首部,不覆盖IP数据报中的任何数据。TCP校验和、IP校验和的计算方法是基本一致的,除了计算的范围不同。

TCP的校验和是必需的,而UDP的校验和是可选的。TCP和UDP计算校验和时,都要加上一个12字节的伪首部。

伪首部

首先解释下伪首部的概念,伪首部的数据都是从IP数据报头获取的。其目的是让TCP检查数据是否已经正确到达目的地,只是单纯为了做校验用的。

struct { unsigned long saddr; //源地址 unsigned long daddr; //目的地址 char mbz; //强制置空 char ptcl; //协议类型 unsigned short tcpl; //TCP长度 }psd_header;12345678

伪首部共有12字节(前96Bits),包含如下信息:源IP地址、目的IP地址、保留字节(置0)、传输层协议号(TCP是6)、TCP报文长度(报头+数据)。

伪首部是为了增加TCP校验和的检错能力:如检查TCP报文是否收错了(目的IP地址)、传输层协议是否选对了(传输层协议号)等。

校验和计算

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.

上述的定义说得很明确: 首先,把伪首部、TCP报头、TCP数据分为16位的字,如果总长度为奇数个字节,则在最后增添一个位都为0的字节。把TCP报头中的校验和字段置为0(否则就陷入鸡生蛋还是蛋生鸡的问题)。 其次,用反码相加法累加所有的16位字(进位也要累加)。 最后,对计算结果取反,作为TCP的校验和。

举个例子来解释该校验方法:

1、首先将检验和置零; 2、然后将TCP伪首部部分,TCP首部部分,数据部分都划分成16位的一个个16进制数 3、将这些数逐个相加,记得溢出的部分加到最低位上,这是循环加法: 0xc0a8+ 0x0166+……+0x0402=0x9b49 4、最后将得到的结果取反,则可以得到检验和位0x64b6

校验和反码求和 的实现

发送方:原码相加 ,并将高位叠加到低位,取反 ,得到反码求和结果,放入校验和 接收方:将所有原码 相加,高位叠加, 如全为1,则正确

下面为C实现较为原始的checksum算法,代码中对于算法做了比较详细的注释:

unsigned short checksum(unsigned short * addr, int count)

{ long sum = 0; /* 计算所有数据的16bit对之和 */ while( count > 1 ) { /* This is the inner loop */ sum += *(unsigned short*)addr++;

count -= 2 }

/* 如果数据长度为奇数,在该字节之后补一个字节(0), 然后将其转换为16bit整数,加到上面计算的校验和 中。 */ if( count > 0 ) { char left_over[2] = {0}; left_over[0] = *addr; sum += * (unsigned short*) left_over; }

/* 将32bit数据压缩成16bit数据,即将进位加大校验和 的低字节上,直到没有进位为止。 */ while (sum>>16) sum = (sum & 0xffff) + (sum >> 16); /*返回校验和的反码*/ return ~sum; } --------------------- 作者:造夢先森 来源:CSDN 原文:https://blog.csdn.net/qq_15437629/article/details/79183076 版权声明:本文为博主原创文章,转载请附上博文链接!

相关推荐

365真正的官网 世界杯球门规格?老球迷来

世界杯球门规格?老球迷来

📅 06-29 👁️ 5584
beat365体育登陆网址 肠袢:了解这一肠道现象

肠袢:了解这一肠道现象

📅 07-31 👁️ 8515
beat365体育登陆网址 八款上网行为管理软件详尽对比,总有一款适合你的企业

八款上网行为管理软件详尽对比,总有一款适合你的企业

📅 07-07 👁️ 8287
beat365体育登陆网址 快手怎么关闭免密支付?如何设置?

快手怎么关闭免密支付?如何设置?

📅 07-01 👁️ 8687
beat365体育登陆网址 绯鱼的意思

绯鱼的意思

📅 07-09 👁️ 1150
365bet.com 世界杯中国往事

世界杯中国往事

📅 06-27 👁️ 2382
365bet.com dnf暗之根源有什么用

dnf暗之根源有什么用

📅 08-01 👁️ 4579
365bet.com 收到执行通知书后多久被强制执行

收到执行通知书后多久被强制执行

📅 07-28 👁️ 1279