这个tcp校验和计算如何计算?

校验和算法分析【转】 - CSDN博客
校验和算法分析【转】
以前看计算机网络相关的书,每次看到IP或者UDP报头校验和时,都一瞥而过,以为相当简单,不就是16bit数据的相加吗。最近在研究《TCP/IP详解卷1:协议》这本书,看到校验和是16bit字的二进制反码和(晕,以前都没注意原来是反码和,看来以前看书不仔细啊!罪过,罪过~~),觉得很奇怪,为什么会用反码和,而不是直接求和呢?(因为我认为TCP/IP协议里面的算法和思想一般都是非常经典的,人家这么做一定有原因的)下面就来探索一下这个校验和算法具体怎么实现的。http://blog.csdn.net/li_xiang1102/article/details/6901660
首先,IP、ICMP、UDP和TCP报文头部都有校验和字段,大小都是16bit,算法也基本一样。
在发送数据时,为了计算数据包的校验和。应该按如下步骤:
  (1)把校验和字段置为0;
  (2)把需校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和;
  (3)把得到的结果存入校验和字段中。
  在接收数据时,计算数据包的校验和相对简单,按如下步骤:
  (1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;
  (2)检查计算出的校验和的结果是否为0;
  (3)如果等于0,说明被整除,校验和是正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。
虽然上面四种报文的校验和算法一样,但在作用范围存在不同:
IP校验和只校验20字节的IP报头;
ICMP校验和覆盖整个报文(ICMP报头+ICMP数据);
UDP和TCP校验和不仅覆盖整个报文,而且还有12字节的IP伪首部,包括源IP地址(4字节)、目的IP地址(4字节)、协议(2字节,第一字节补0)和TCP/UDP包长(2字节)。另外UDP、TCP数据报的长度可以为奇数字节,所以在计算校验和时需要在最后增加填充字节0(注意,填充字节只是为了计算校验和,可以不被传送)。
这里还要提一点,UDP的校验和是可选的,当校验和字段为0时,表明该UDP报文未使用校验和,接收方就不需要校验和检查了!那如果UDP校验和的计算结果是0时怎么办呢?书上有这么一句话:“如果校验和的计算结果为0,则存入的值为全1(65535),这在二进制反码计算中是等效的。”
讲了这么多,那这个校验和到底是怎么算的呢?
什么是二进制反码求和
对一个无符号的数,先求其反码,然后从低位到高位,按位相加,有溢出则向高位进1(跟一般的二进制加法规则一样),若最高位有进位,则向最低位进1。
首先这里的反码好像跟我们以前学的有符号数的反码不一样(即正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各位取反),这里不分正负数,直接每个位都取反!
上面加粗的那句是跟我们一般的加法规则不太一样的地方:最高位有进位,则向最低位进1。确实有些疑惑,为什么要这样做呢?仔细分析一下(为了方便说明,以4bit二进制反码求和举例),上面的这种操作,使得在发生加法进位溢出时,溢出的值并不是10000,而是1111。也即是当相加结果满1111时溢出,这样也可以说明为什么0000和1111都表示0了(你同样可以发现,任何数与这两个数做二进制反码求和运算结果都是原数,这恰好符合数0的加法意义)。
&&&&&&& 下面再举例两种二进制反码求和的运算:
&&&&&&& 原码加法运算&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
反码加法运算
&&&&&&& 3(0011)+ 5(0101)=
8(1000)&&&&& 3(1100)+
5(1010)=& 8(0111)
&&&&&&& 8(1000)+ 9(1001)=
1(0001)&&&&& 8(0111)+
9(0110)=& 2(1101)
&&&&&&& 从上面两个例子可以看出,当加法未发生溢出时,原码与反码加法运算结果一样;当有溢出时,结果就不一样了,原码是满10000溢出,而反码是满1111溢出,所以相差正好是1。举例只是为了形象地观察二进制反码求和的运算规则,至于为什么要定义这样的规则以及该运算规则还存在其它什么特性,可能就需要涉及代数理论的东西的了(呜呜~~数学理论没学好啊,只能从表面上分析分析)。
&&&&&&& 另外关于二进制反码求和运算需要说明的一点是,先取反后相加与先相加后取反,得到的结果是一样的!(事实上我们的编程算法里,几乎都是先相加后取反。)
校验和算法的实现
讲了什么是二进制反码求和,那么校验和的算法实现就简单多了。废话少说,直接上代码:
1&&&&&&&&//计算校验和&
2&&&&&&&&USHORT checksum(USHORT
*buffer,int size)&
3&&&&&&&&{&
4&&&&&&&&&&&&unsigned
long cksum=0;&
5&&&&&&&&&&&&while(size&1)&
6&&&&&&&&&&&&{&
7&&&&&&&&&&&&&&&&cksum+=*buffer++;&
8&&&&&&&&&&&&&&&&size-=sizeof(USHORT);&
9&&&&&&&&&&&&}&
&&&&if(size)&
&&&&&&&&cksum+=*(UCHAR *)&
&&&&//将32位数转换成16&
&&&&while (cksum&&16)&
&&&&&&&&cksum=(cksum&&16)+(cksum &0xffff);&
&&&&return (USHORT) (~cksum);&
buffer是指向需校验数据缓存区的指针,size是需校验数据的总长度(字节为单位)
4~13行代码对数据按16bit累加求和,由于最高位的进位需要加在最低位上,所以cksum必须是32bit的unsigned
long型,高16bit用于保存累加过程中的进位;另外代码10~13行是对size为奇数情况的处理!
14~16行代码的作用是将cksum高16bit的值加到低16bit上,即把累加中最高位的进位加到最低位上。这里使用了while循环,判断cksum高16bit是否非零,因为第16行代码执行的时候,仍可能向cksum的高16bit进位。
有些地方是通过下面两条代码实现的:
cksum = (cksum && 16) + (cksum & 0xffff);
cksum +=(cksum &&16);
这里只进行了两次相加,即可保证相加后cksum的高16位为0,两种方式的效果一样。事实上,上面的循环也最多执行两次!
17行代码即对16bit数据累加的结果取反,得到二进制反码求和的结果,然后函数返回该值。
为什么使用二进制反码求和呢?
好了,最后一个问题,为什么要使用二进制反码来计算校验和呢,而不是直接使用原码或者补码?
这个问题我想了很久,由于水平有限实在弄不明白,于是在百度上一阵狂搜,什么都没有(不知道是百度不给力,还是大家都不关注这个问题呢?)。果断换google,敲了3个关键词:why
checksum tcp,嘿嘿结果第二篇就是我想要的文章了!!!
先把链接给大家吧:
这篇文章主要介绍二进制反码求和(the 1's complement sum)与补码求和(the 2's complement
sum)的区别,另外还说明了在TCP/IP校验和中使用反码求和的优点。
It may look awkword to use a 1'scomplement addition on 2's complement machines. This method however has its ownbenefits.
Probably the most important is that itis endian independent. Little Endian computers store hex numbers with the LSBlast (Intel processors for example). Big Endian computers put the
LSB first(IBM mainframes for example). When carry is added to the LSB to form the 1'scomplement sum (see the example) it doesn't matter if we add 03 + 01 or 01 +03. The result is the same.
Other benefits include the easiness of checking the transmission and the checksum calculation plus a variety of ways to speed up the calculation by updating only IP fields that have
&&&&&&&上面是原文的一部分,说明在TCP/IP校验和中使用反码求和的一些优点:
a.不依赖系统是大端还是小端。即无论你是发送方计算或者接收方检查校验和时,都不需要调用htons
或者 ntohs,直接通过上面第2节的算法就可以得到正确的结果。这个问题你可以自己举个例子,用反码求和时,交换16位数的字节顺序,得到的结果相同,只是字节顺序相应地也交换了;而如果使用原码或者补码求和,得到的结果可能就不相同!
b.计算和验证校验和比较简单,快速。说实话,这个没怎么看明白,感觉在校验和计算方面,原码或者补码求和反而更简单一些(从C语言角度),在校验和验证上面,通过一样的算法判断结果是否为全0,确实要方便一些,所以可能从综合考虑确实反码求和要简便一些。另外,IP报文在传输过程中,路由器经常只修改TTL字段(减1),此时路由器转发该报文时可以直接增加它的校验和,而不需要对IP整个首部进行重新计算。当然,可能从汇编语言的角度看,反码求和还有很多高效的地方,这里就不在深入追究了~~~
结语:本来一个不怎么注意的地方,深入探究一下竟然发现这么多东西。学习算法其实没有必要抱着《算法导论》一页一页地啃(嘿嘿,哥也有一本哦),我更喜欢从TCP/IP协议或LInux内核原理中去探究算法以及实现思想,这样反倒更有趣,而且这里面的一些算法和思想相当经典,慢慢体会,必然受益匪浅!
本文已收录于以下专栏:
相关文章推荐
校验和思路首先,IP、ICMP、UDP和TCP报文头都有检验和字段,大小都是16bit,算法基本上也是一样的。在发送数据时,为了计算数据包的检验和。应该按如下步骤:1、把校验和字段设置为0;2、把需要...
首先,IP、ICMP、UDP和TCP报文头部都有校验和字段,大小都是16bit,算法也基本一样:
在发送数据时,为了计算数据包的校验和。应该按如下步骤:
(1)把校验和字段置为0; 
(2)把需校验的...
转自:http://blog.csdn.net/namelcx/article/details/6866720
1. 前言
校验和计算是NAT功能和内容修改功能的基本功,这些操作进行后都需要修...
每周荐书:Java Web、Python极客编程、移动Web前端(评论送书) 各位抱歉,上周活动停更一周,本周继续感谢大家对每周荐书栏目的支持,先公布下上期活动中奖名单 微雨燕凝霜寒森林之舟架构探险:...
1、算法思路:
       IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法如下:
  在发送数据时,为了计算IP数据包的校验和。应该按如下步骤:
本篇博文以上一篇文章《TCP、IP、ARP、ICMP首部分析》为基础,根据STM32中以太网程序来着重看一下,以太网数据包的解析过程。
unsigned char ip_hdr_8[] =
0x45,0x00,
0x00,0x3c,
0x00,0x00,
0x00,0x00,
常见的数据校验方法
1.      校验是什么
校验,是为保护数据的完整性,用一种指定的算法对原始数据计算出的一个校验值。当接收方用同样的算法再算一次校验值,如果两次校验值一样,表示数据完整。
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)本帖子已过去太久远了,不再提供回复功能。6053人阅读
计算机网络(1)
校验和思路
首先,IP、ICMP、UDP和TCP报文头都有检验和字段,大小都是16bit,算法基本上也是一样的。
在发送数据时,为了计算数据包的检验和。应该按如下步骤:
1、把校验和字段设置为0;
2、把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和;
3、把得到的结果存入校验和字段中
在接收数据时,计算数据包的检验和相对简单,按如下步骤:
1、把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;
2、检查计算出的校验和的结果是否为0;
3、如果等于0,说明被整除,校验和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。
虽然说上面四种报文的校验和算法一样,但是在作用范围存在不同:IP校验和只校验20字节的IP报头;而ICMP校验和覆盖整个报文(ICMP报头+ICMP数据);UDP和TCP校验和不仅覆盖整个报文,而且还有12个字节的IP伪首部,包括源IP地址(4字节)、目的IP地址(4字节)、协议(2字节)、TCP/UDP包长(2字节)。另外UDP、TCP数据报的长度可以为奇数字节,所以在计算校验和时需要在最后增加填充字节0(填充字节只是为了计算校验和,可以不被传送)。
校验和计算方法:
对一个无符号的数,先求其反码,然后从低位到高位,按位相加,有益处则向高位进1(和一般的二进制法则一样),若最高位有进位,则向最低位进1.
特点:关于二进制反码循环移位求和运算需要说明的一点是,先取反后相加与先相加后取反,得到的结果是一样的。
可结合性和可交换性
用A,B,C,D,E,F分别表示一个8位的二进制数(一个字节),用[A, B]这样的形式表示A*256+B,那么16位校验和可以用个如下形式给出
sum = [A,B]+’[C,D]+’[E,F];
其中, +’被表示二进制循环移位加法
可结合性:[A,B]+’[C,D]+’[E,F] = [A,B]+’([C,D]+’[E,F])
可交换性:[A,B]+’[C,D]+’[E,F] = [C,D]+’[A,B]+’[E,F]
字节自主性
[A,B]+’[C,D]+’[E,F] = [B,A]+’([D,C]+’[F,E])
由于若最高位有进位,则向最低位进1 这样的特性,第15位到0位进位,第7位向第8位进位,所以,整个求和结果是一样的。
有些机器的字处理长度是16的倍数,这样可以提高他的计算速度,由于可结合行,那么32位机器可以[A,B,C,D]+’…进行32校验和。
为什么使用二进制反码循环移位加法呢?
我们知道,计算机中有原码,反码,补码,为什么要使用二进制反码来计算校验和呢,而不是直接使用原码或者是补码呢?
二进制反码循环移位加法求和优点
不依赖系统是大端小端。即无论你是发送方计算机或者接收方检查校验和时,都不要调用htons或者ntohs,直接通过上面的算法就可以得到正确的结果。这个问题你可以自己举个例子,用反码求和时,交换16位数的字节顺序,得到的结果相同,只是字节顺序相应地也交换了;而如果使用原码或者补码求和,得到的结果可能就不同。
计算和验证校验和比较简单、快递。
对于一串16进制数据:f5f6f7
正常顺序是将高8位*256之后,即将高位向左移动8位,加上低8位,交换顺序反之
可以明显得到,二进制反码循环移位加法与字节序无关。
#include&iostream&
#include&cstdio&
#include&cstdlib&
#include&cstring&
void main(int argc, char *argv[])
unsigned char LowChar, HighC
unsigned int count = 0, checksum = 0, byte = 0;
unsigned long int sum = 0;
if ((fp = fopen("I:\\1.txt", "r")) == NULL)
printf("File cannot be opened!");
system("pause");
printf("4位
if ((ch = fgetc(fp))!=EOF)
if (ch != ' ')
if (ch &= '0' && ch &= '9')
ch -= '0';
else if (ch &= 'a' && ch &= 'f')
ch = ch-'a'+10;
else if(ch &= 'A' && ch &= 'F')
ch = ch-'A'+ 10;
if (count%2 == 1)
HighChar = ch && 4;
LowChar = ch & 0x0f;
byte = HighChar|LowC
if (count % 4 == 2)
sum += byte && 8;
else if(count % 4 == 0)
sum += byte;
printf("%04x -- %8lx
\n", byte, sum);
if ( sum && 16)
checksum = ~(long(sum&&16)+long(sum&0x0000ffff));
printf("\n移位后sum: %x", (long(sum&&16)+long(sum&0x0000ffff)));
printf("\nCheckSum1: %x", checksum);
checksum = checksum&0x0000ffff;
printf("\nCheckSum: %x\n", checksum);
system("pause");
参考博客:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:100410次
积分:2171
积分:2171
排名:第18413名
原创:118篇
(1)(1)(5)(2)(2)(1)(6)(23)(27)(20)(8)(19)(3)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'计算校验和_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
计算校验和
阅读已结束,下载文档到电脑
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩13页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢串口调试的时候校验和怎么计算-专业自动化论坛-中国工控网
串口调试的时候校验和怎么计算
给TA发消息
加TA为好友
悬赏10分-已结帖
发表于: 20:54:57
我想问下校验和是怎么计算的啊!例如30H+31H。又或者3AH+3BH+3CH+35H+38H是多少,怎么加的啊?
给TA发消息
加TA为好友 发表于: 10:33:40 1楼
ASCII 字符相加就可以了。
给TA发消息
加TA为好友 发表于: 11:11:10 2楼
有专门的计算器,在网上下载一个,不需要研究具体怎么加。例如下面这个:
给TA发消息
加TA为好友 发表于: 11:16:03 3楼
你实在要想自己计算,请下载台达的这个文档——台达PLC通讯协议v1.1,里面有详细计算方法。
给TA发消息
加TA为好友 发表于: 12:10:30 4楼
我一直没去计算过校验值,偷懒,只用了PLC自带的指令,不管校验码。
给TA发消息
加TA为好友 发表于: 13:10:35 5楼
首先搞清楚是仕么校验码? 校验码有很多种, 典型的Modbus 协议中 ,有 RTU 协议对应的 CRC (冗余循环校验码),ASCII&&&&&协议中的&LRC (累加和校验码) 。 还有奇偶校验 等等。 &到网上查一下,具体的校验码 计算公式,原理。。。。。&一般来说,校验码 就是对通讯 数据帧 当字节流 按一定公式计算后 得出校验码!&
给TA发消息
加TA为好友 发表于: 13:58:13 6楼
校验和是吧,根据协议定义,也不一样,通常的做法是去掉头尾,将所有的字节相加,取一个自己大小作为校验和
给TA发消息
加TA为好友 发表于: 11:00:04 7楼
(1)求和:11E;(2)转化成2进制:;(3)然后取反:;(4)再加1: = E2(最终结果校验码)
给TA发消息
加TA为好友 发表于: 09:37:18 8楼
回复内容:对:秦君_1关于有专门的计算器,在网上下载一个,不需要研究具体怎么加。例如下面这个:内容的回复:你可以发一个到我邮箱吗?好像下载都注册那些。。。
给TA发消息
加TA为好友 发表于: 10:17:36 9楼
校验的方法很多比如求和校验,异或校验等等吧,这类校验,只注重校验值的大小,比如校验用一个字节,前面的数据按规则进行就可以了,最后一个字节是什么就是什么,这种校验相对比较简单,速度快,但是对于多数据传输可靠性比较低。还有比较常用的 比如CRC校验,这个校验比较可靠,用的很多,实现相对也方便,大致实现的方法有两种,从底层上讲 比如使用查表,比如按照流程对校验值进行按步骤操作最后得到CRC校验码,这个流程都是固定的,网上很多。&关键看你使用的是哪种校验
给TA发消息
加TA为好友 发表于: 11:38:07 10楼
留下邮箱,我发给你一个 自己 DIY 的 码制转换工具,自带CRC 校验哦,
给TA发消息
加TA为好友 发表于: 11:50:03 11楼
我也要一個.謝謝.
给TA发消息
加TA为好友 发表于: 15:20:13 12楼
校验方式有很多:有奇校验和偶校验,CRC校验楼上几位说的都是CRC校验应用也比较多,下边介绍一下CRC校验计算方法1、循环校验码(CRC码):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。2、生成CRC码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。3、CRC码集选择的原则:若设码字长度为N,信息字段为K位,校验字段为R位(N=K+R),则对于CRC码集中的任一码字,存在且仅存在一个R次多项式g(x),使得V(x)=A(x)g(x)=xRm(x)+r(x);其中:&&& m(x)为K次信息多项式, r(x)为R-1次校验多项式,&&&&&&&& g(x)称为生成多项式:g(x)=g0+g1x+ g2x2+...+g(R-1)x(R-1)+gRxR发送方通过指定的g(x)产生CRC码字,接收方则通过该g(x)来验证收到的CRC码字。标准CRC生成多项式如下表:&& 名称&&&&&&& 生成多项式&&&&&&&&&&&&& 简记式*&& 标准引用 && CRC-4&&&&&& x4+x+1&&&&&&&&&&&&&&&&& 3&&&&&&&& ITU G.704 && CRC-8&&&&&& x8+x5+x4+1&&&&&&&&&&&&& 0x31&&&&&&&&&&&&&&&&&&& && CRC-8&&&&&& x8+x2+x1+1&&&&&&&&&&&&& 0x07&&&&&&&&&&&&&&&&&&& && CRC-8&&&&&& x8+x6+x4+x3+x2+x1&&&&&& 0x5E && CRC-12&&&&& x12+x11+x3+x+1&&&&&&&&& 80F&& CRC-16&&&&& x16+x15+x2+1&&&&&&&&&&& 8005&&&&& IBM SDLC&& CRC16-CCITT x16+x12+x5+1&&&&&&&&&&& 1021&&&&& ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS && CRC-32&&&&& x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS && CRC-32c&&&& x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP基本算法(人工笔算):&& 以CRC16-CCITT为例进行说明,CRC校验码为16位,生成多项式17位。假如数据流为4字节:BYTE【3】、BYTE【2】、BYTE【1】、BYTE【0】;数据流左移16位,相当于扩大256×256倍,再除以生成多项式0x11021,做不借位的除法运算(相当于按位异或),所得的余数就是CRC校验码。发送时的数据流为6字节:BYTE【3】、BYTE【2】、BYTE【1】、BYTE【0】、CRC【1】、CRC【0】;举例:信息字段代码为: m(x)=x6+x4+x3+1&&& 代码为:<span style="color:#1 生成多项式:&&& g(x)=x4+x3+1&&&&&& 代码为:11001m(x)x4=x10+x8+x7+x4 对应的代码记为:&&&& 即 左移4位m(x)x4 在与 g(x)进行 模2的除法运算,相当于按位异或,计算过程如下:1 0 1 1 0 0 1 0 0 0 01 1 0 0 1-----------------------------0 1 1 1 1 0 1 0 0 0 01 1 0 0 1-----------------------------0 0 0 1 1 1 1 0 0 0 0&&&&& 1 1 0 0 1-----------------------------&&&&& 0 0 1 1 1 0 0 0 &&&&&&&&& 1 1 0 0 1 -----------------------------&&&&&&&&& 0 0 1 0 1 0&&&&&&&&&&&& --------------& 余数&&&& 即 校验码&&发送数据码为: <span style="color:#11010
给TA发消息
加TA为好友 发表于: 16:19:13 13楼
廖常初老师自己开发的串口调试助手可以计算多种校验:异或校验、求和校验、CRC校验、LRC校验等需要的话,分给我,联系我QQ。我发给你!
给TA发消息
加TA为好友 发表于: 20:55:28 14楼
回复内容:对:miy_gongkong关于留下邮箱,我发给你一个 自己 DIY 的 码制转换工具,自带CRC 校验哦,内容的回复:
给TA发消息
加TA为好友 发表于: 10:09:22 15楼
&& 我也要一個.謝謝. “
给TA发消息
加TA为好友 发表于: 11:16:16 16楼
用vb自己写一个小软件用或者网上下载一个这样的啊!
给TA发消息
加TA为好友 发表于: 22:14:50 17楼
回复内容:对: ljbcompany
(1)求和:11E;(2)转化成2进制:1000111... 内容的回复!&哥,我觉得你讲的最简单直观而且容易理解。帮我大忙了。
周点击排行周回复排行
[167] [165] [158] [143] [137] [123] [122] [114] [112] [102]
[112] [101] [21] [19] [16] [15] [9] [9] [8] [8]最新求助
[2] [6] [6] [0] [2] [3] [21] [2] [5] [15]

我要回帖

更多关于 bbc校验码如何计算 的文章

 

随机推荐