《计算机网络课程设计(第2版)》——3.5节相关扩展

3.5 相关扩展
除了上面介绍的方法之外,还有其他一些算法可以完成CRC校验。例如,多项式除法可用除法电路来实现。除法电路的主体由一组移位寄存器和模2加法器(异或单元)组成。以CRC-ITU为例,它由16级移位寄存器和3个加法器组成,图3-5给出了除法电路实现CRC的示意图(编码/解码共用)。编码、解码前将各寄存器初始化为“1”,信息位按照时钟周期依次移入。当信息位全部输入后,从寄存器组输出CRC结果。
1. 比特型算法
上面的CRC-ITU除法电路可以用软件来模拟。定义一个寄存器组,初始化为全1。依照电路图,每输入一个信息位,相当于一个时钟脉冲到来,从高到低依次移位。移位前信息位与bit0相加产生临时位,其中bit15移入临时位,bit10、bit3还要加上临时位。当全部信息位输入完成后,从寄存器组取出它们的值,这就是CRC码。
该算法的代码如下:

typedef union {
    u16 val;
    struct {
        u16 bit0 : 1;
        u16 bit1 : 1;    //定义寄存器结构体
        ...
    } bits;
} CRCREGS;
// 寄存器组
CRCREGS regs;
// 初始化CRC寄存器组: 移位寄存器置为全1
void crcInitRegisters()
{
    regs.val = 0xffff;
}
// CRC输入一位
void crcInputBit(bit in)
{
    bit a;
    a = regs.bits.bit0 ^ in;
    regs.bits.bit0 = regs.bits.bit1;
    regs.bits.bit1 = regs.bits.bit2;
    regs.bits.bit2 = regs.bits.bit3;
    regs.bits.bit3 = regs.bits.bit4 ^ a;
    regs.bits.bit4 = regs.bits.bit5;
    regs.bits.bit5 = regs.bits.bit6;
    regs.bits.bit6 = regs.bits.bit7;
    regs.bits.bit7 = regs.bits.bit8;
    regs.bits.bit8 = regs.bits.bit9;
    regs.bits.bit9 = regs.bits.bit10;
    regs.bits.bit10 = regs.bits.bit11 ^ a;
    regs.bits.bit11 = regs.bits.bit12;
    regs.bits.bit12 = regs.bits.bit13;
    regs.bits.bit13 = regs.bits.bit14;
    regs.bits.bit14 = regs.bits.bit15;
    regs.bits.bit15 = a;
}
// 输出CRC码(寄存器组的值)
u16 crcGetRegisters()
{
    return regs.val;
}
crcInputBit中的逐步移位/异或操作可以进行如下简化:
void crcInputBit(bit in)
{
    bit a;
    a = regs.bits.bit0 ^ in;
    regs.val >>= 1;
    if(a) regs.val ^= 0x8408;

  1. 字节型算法
    比特型算法逐位进行运算,效率比较低,不适用于高速通信的场合。数字通信系统(遵循各种通信标准)一般是对一帧数据进行CRC校验,而字节是帧的基本单位。最常用的是一种按字节查表的快速算法。该算法基于这样一个事实:计算本字节后的CRC码,等于上一字节CRC右移8位和本字节之和再与上一字节余式CRC码的低8位左移8位相加后所求得的CRC码。如果我们把8位二进制序列数的CRC(共256个)全部计算出来,放在一个表里,那么编码时只要从表中查找对应的值进行处理即可。
    CRC-ITU的算法如下:
    1) 寄存器组初始化为全1(0xFFFF)。
    2) 寄存器组向右移动一个字节。
    3) 刚移出的那个字节与数据字节进行异或运算,得出一个指向值表的索引。
    4) 将索引所指的表值与寄存器组做异或运算。
    5) 数据指针加1,如果数据没有全部处理完,则重复步骤2。
    6) 寄存器组取反,得到CRC,附加在数据之后。
    CRC-ITU的验证算法如下:
    1) 寄存器组初始化为全1(0xFFFF)。
    2) 寄存器组向右移动一个字节。
    3) 刚移出的那个字节与数据字节进行异或运算,得出一个指向值表的索引。
    4) 将索引所指的表值与寄存器组做异或运算。
    5) 数据指针加1,如果数据没有全部处理完,则重复步骤2(数据包括CRC的两个字节)。
    6) 判断寄存器组的值是否等于“Magic Value”(0xF0B8),若相等则通过,否则失败。
    下面是通用的CRC-ITU查找表以及计算和验证CRC的C语言程序:
// CRC-ITU查找表
const u16 crctab16[] =
{
    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
};

// 计算给定长度数据的16位CRC
u16 GetCrc16(const byte* pData, int nLength)
{
    u16 fcs = 0xffff;            // 初始化
       while(nLength>0)
    {
        fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff];
        nLength--;
        pData++;
    }
       return ~fcs;               // 取反
}

// 检查给定长度数据的16位CRC是否正确
bool IsCrc16Good(const byte* pData, int nLength)
{
    u16 fcs = 0xffff;            // 初始化
        while(nLength>0)
    {
        fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff];
        nLength--;
        pData++;
    }
        return (fcs == 0xf0b8);  // 0xf0b8是CRC-ITU的"Magic Value"
}
时间: 2024-07-29 12:50:32

《计算机网络课程设计(第2版)》——3.5节相关扩展的相关文章

《计算机网络课程设计(第2版)》——1.1节计算机网络课程的教学特点

第1章 计算机网络课程教学.实验与课程设计的关系 1.1 计算机网络课程的教学特点在进行计算机网络课程设计之前,我们需要对计算机网络课程的教学大纲.学习要求与教材体系做一个说明.因为不同的教材对学习内容的安排有所差异,但是本书综合考虑了不同教材的基本特点,总结计算机网络课程中必须掌握的基础知识与基本技能,在此基础上选择了14个课程设计的课题.根据计算机网络技术的特点,在计算机网络课程教学的组织中需要处理好以下三个方面的关系. 计算机技术知识与通信知识的关系从计算机科学与技术学科的角度来看,计算机

《计算机网络课程设计(第2版)》——1.3节计算机网络课程的知识点

1.3 计算机网络课程的知识点 1. 组织计算机网络课程的知识点 在组织计算机网络课程的知识点时,一般都是以Internet技术与高速网络技术为主线,加入网络发展的最新成果. 网络最重要的应用是Internet.Internet对科技进步和社会发展的影响是非常显著的,并且这种影响还在继续扩大,这也正体现出网络技术发展的生命力.因此,学习网络知识重要的是通过学习网络的基本知识,认识Internet的核心技术,理解Internet的实现方法.通过本课程的学习,学生能够初步掌握网络和Internet技

《计算机网络课程设计(第2版)》——导读

目 录 第一部分 课程设计目标第1章 计算机网络课程教学.实验与课程设计的关系 1.1 计算机网络课程的教学特点1.2 计算机网络课程的实验教学与课程设计的关系 1.3 计算机网络课程的知识点 1.4 课程设计要求及评分标准 第二部分 课程设计指导第2章 计算校验和 2.1 课程设计目的 2.2 课程设计要求 2.3 相关知识 2.4 课程设计分析 2.5 相关扩展 第3章 封装Ethernet帧 3.1 课程设计目的 3.2 课程设计要求 3.3 相关知识 3.4 课程设计分析 3.5 相关扩

《计算机网络课程设计(第2版)》——1.4节课程设计要求及评分标准

1.4 课程设计要求及评分标准 安排网络课程设计的目的有两个:一是引导学生将书本上抽象的概念与具体实现技术结合起来,使学习深化:二是消除学生对协议的神秘感,调动学生学习的积极性与主动性. 网络课程设计基本是按照上述的知识体系安排的.本书中的14个课程设计课题基本覆盖了上述4个学习单元的主要内容.每个题目都具有一定的代表性,希望学生通过完成课程设计课题,体会网络协议设计与实现过程,以及专业技术人员所使用的基本方法和技巧. 课程设计要求: 1) 正确理解题意. 2) 有良好的编程规范和适当的注释.

《计算机网络课程设计(第2版)》——3.1节课程设计目的

第 3 章 封装Ethernet帧 3.1 课程设计目的帧是在数据链路层中进行数据传输的基本单位.熟悉帧结构对于理解网络协议的概念.网络层次结构与协议执行过程具有重要意义.本课程设计的主要目的是通过封装Ethernet帧,了解Ethernet帧中各个字段的含义与用途.

《计算机网络课程设计(第2版)》——3.4节课程设计分析

3.4 课程设计分析 1. 填充帧头部字段 要完成一次帧封装的过程,首先要完成的就是帧头部的装入,这一过程非常简单,只要将前导码.定界符.目的地址.源地址.长度字段的相应数值按顺序写入就可以了.其中,长度字段的值即为要发送的数据的实际长度.我们可以通过以下两种方式来获得长度字段的值. 方法一 while(!in.eof()) //读数据至缓冲区buf { in.get(a); buf[j]=a; //通过j来记录输入数据的长度 j++; } 方法二 infile.open(argv[1],ios

《计算机网络课程设计(第2版)》——2.4节课程设计分析

2.4 课程设计分析 校验和的计算过程主要分为三个步骤:数据文件的输入.校验和的计算和校验结果的输出.其中,主要的是数据的输入和校验和的计算. 1. 数据的输入方式 输入数据可能是以字符形式存储的,而校验和的计算则要采用数据形式,所以在从文件读取数据时,都要进行字符到数据的相互转换. 1) 将读入的ASCII码转化为相应的整型变量. if(ch>='0'&&ch<='9') ch-='0'; else { if(ch>='a'&&ch<='f') c

《计算机网络课程设计(第2版)》——3.2节课程设计要求

3.2 课程设计要求 根据后面介绍的IEEE 802.3帧结构,编写程序将指定数据封装为Ethernet帧. 1)以命令行形式运行: EncapFrame input_file output_file 其中,EncapFrame为程序名,input_file为输入数据文件,output_file为输出数据文件. 2)输出内容:Ethernet帧的各字段内容.

《计算机网络课程设计(第2版)》——2.2节课程设计要求

2.2 课程设计要求根据后面介绍的校验和算法,编写程序为给定数据计算校验和.1) 以命令行形式运行: Checksum input_file 其中Checksum为程序名,input_file为输入数据文件名.2) 输出内容:数据文件的校验和.

《计算机网络课程设计(第2版)》——2.3节相关知识

2.3 相关知识 校验和的概念网络上的数据最终都是通过物理传输线路进行传输的,如果高层没有采用差错控制,那么物理层传输的数据可能有差错.为了保证传输数据的正确性,在物理层的基础上设计了数据链路层.设计数据链路层的主要目的就是在原始的.有差错的物理传输线路的基础上,采用差错检测.差错控制与流量控制等方法,将有差错的物理线路改进成逻辑上无差错的数据链路,以向网络层提供高质量的服务. 目前,进行差错检测和控制的主要方法是:发送方在需要发送的数据后面增加一定的冗余信息,这些冗余信息通常是通过对发送的数据