Ethernet帧结构解析..
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验一Ethernet帧结构解析
一.需求分析
实验目的:(1)掌握Ethernet帧各个字段的含义与帧接收过程;
(2)掌握Ethernet帧解析软件设计与编程方法;
(3)掌握Ethernet帧CRC校验算法原理与软件实现方法。
实验任务:(1)捕捉任何主机发出的Ethernet 802.3格式的帧和DIX Ethernet V2(即Ethernet II)格式的帧并进行分析。
(2)捕捉并分析局域网上的所有ethernet broadcast帧进行分析。
(3)捕捉局域网上的所有ethernet multicast帧进行分析。
实验环境:安装好Windows 2000 Server操作系统+Ethereal的计算机
实验时间; 2节课
二.概要设计
1.原理概述:
以太网这个术语通常是指由DEC,Intel和Xerox公司在1982年联合公布的一个标准,它是当今TCP/IP采用的主要的局域网技术,它采用一种称作CSMA/CD的媒体接入方法。几年后,IEEE802委员会公布了一个稍有不同的标准集,其中802.3针对整个CSMA/CD网络,802.4针对令牌总线网络,802.5针对令牌环网络;此三种帧的通用部分由802.2标准来定义,也就是我们熟悉的802网络共有的逻辑链路控制(LLC)。以太网帧是OSI参考模型数据链路层的封装,网络层的数据包被加上帧头和帧尾,构成可由数据链路层识别的数据帧。虽然帧头和帧尾所用的字节数是固定不变的,但根据被封装数据包大小的不同,以太网帧的长度也随之变化,变化的范围是64-1518字节(不包括8字节的前导字)。
帧格式Ethernet II和IEEE802.3的帧格式分别如下。
EthernetrII帧格式:
----------------------------------------------------------------------------------------------
| 前序| 目的地址| 源地址| 类型| 数据
| FCS |
----------------------------------------------------------------------------------------------
| 8 byte | 6 byte | 6 byte | 2 byte | 46~1500 byte | 4 byte|
IEEE802.3一般帧格式
-----------------------------------------------------------------------------------------------------------
| 前序| 帧起始定界符| 目的地址| 源地址| 长度| 数据| FCS | -----------------------------------------------------------------------------------------------------------
| 7 byte | 1 byte | 2/6 byte | 2/6 byte| 2 byte| 46~1500 byte | 4 byte | Ethernet II和IEEE802.3的帧格式比较类似,主要的不同点在于前者定义的2字节的类型,而后者定义的是2字节的长度;所幸的是,后者定义的有效长度值与前者定义的有效类型值无一相同,这样就容易区分两种帧格式
2程序流程图:
三.详细设计:
1.CRC校验部分设计:
为了对以太网帧的对错进行检验,需要设计CRC校验部分。采用以为相与的方式对帧的首部相继作8位CRC校验
输入参数:
chCurrByte 低8位数据有效,记录了上一次CRC校验的余数
chNextByte 低8位数据有效,记录了本次要继续校验的一个字节
传出参数:
chCurrByte 低8位数据有效,记录了本次CRC校验的余数
void checkCRC(int &chCurrByte, int chNextByte)
{
// CRC循环:每次调用进行8次循环,处理一个字节的数据。
for (int nMask = 0x80; nMask > 0; nMask >>= 1)
{
if ((chCurrByte & 0x80) != 0) // 首位为1:移位,并进行异或运算
{
chCurrByte <<= 1; // 移一位
if ( (chNextByte & nMask) != 0) // 补一位
{
chCurrByte |= 1;
}
chCurrByte ^= 7; // 首位已经移出,仅对低8位进行异或运算,7的二进制为0000,0111
}
else // 首位为0,只移位,不进行异或运算
{
chCurrByte <<= 1; // 移一位
if ( (chNextByte & nMask) != 0) // 补一位
{
chCurrByte |= 1;
}
}
}
}
2.部分变量的声明:
int nSN = 1; // 帧序号
int nCheck = 0; // 校验码
int nCurrDataOffset = 22; // 帧头偏移量
int nCurrDataLength = 0; // 数据字段长度
bool bParseCont = true; // 是否继续对输入文件进行解析
int nFileEnd = 0; // 输入文件的长度
3.计算数据段的长度:
nCurrDataLength =
bParseCont ? // 是否到达文件末尾
(file.tellg() - 8 - 1 - nCurrDataOffset) : // 没到文件末尾:下一帧头位置- 前导码和定界符长度- CRC校验码长度- 数据字段起始位置
(file.tellg() - 1 - nCurrDataOffset); // 已到达文件末尾:文件末尾位置- CRC校验码长度- 数据字段起始位置
4.主函数的设计:
void main(int argc, char* argv[])
{
// 检测命令行参数的正确性
if (argc != 2)
{
cout << "请以帧封装包文件为参数重新执行程序" << endl;
exit(0);
}
// 检测输入文件是否存在,并可以按所需的权限和方式打开
ifstream file(argv[1], ios::in|ios::binary|ios::nocreate);
if (!file.is_open())
{
cout << "无法打开帧封装包文件,请检查文件是否存在并且未损坏" << endl;
exit(0);