Ethernet帧结构解析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
bool bAccept = true; //是否接受该帧
//输出帧的序号
cout << endl << "序号:\t\t" << nSN;
//输出前导码,只输出,不校验
cout << endl << "前导码:\t";
for (i = 0; i < 7; i++) //输出格式为:AA AA AA AA AA AA AA
if (!file.is_open())
{
cout << "无法打开帧封装包文件,请检查文件是否存在并且未损坏" << endl;
exit(0);
}
//变量声明及初始化
int nSN = 1; //帧序号
int nCheck = 0; //校验码
int nCurrDataOffset = 22; //帧头偏移量
{
if ((chCurrByte & 0x80) != 0) //首位为1:移位,并进行异或运算
{
chCurrByte <<= 1; //移一位
if ( (chNextByte & nMask) != 0) //补一位
{
chCurrByte |= 1;
}
chCurrByte ^= 7; //首位已经移出,仅对低8位进行异或运算,7的二进制为0000,0111
file.seekg(0, ios::beg); //文件指针位置初始化
cout.fill('0'); //显示初始化
cout.setf(ios::uppercase); //以大写字母输出
//定位到输入文件中的第一个有效帧
//从文件头开始,找到第一个连续的“AA-AA-AA-AA-AA-AA-AA-AB”
if (i == 0) //第一个字节,作为“余数”等待下一个bit
{
nCheck = c;
}
else //开始校验
{
checkCRC(nCheck, c);
}
}
//输出源地址,并校验
cout << endl << "源地址:\t";
for (i = 0; i < 6; i++) //输出格式为:xx-xx-xx-xx-xx-xx
{
cout.width(2);
cout << hex << file.get() << dec << " ";
}
//输出帧前定界符,只输出,不校验
cout << endl << "帧前定界符:\t";
cout.width(2); //输出格式为:AB
cout << hex << file.get();
2程序流程图:
三.详细设计:
1.CRC校验部分设计:
为了对以太网帧的对错进行检验,需要设计CRC校验部分。采用以为相与的方式对帧的首部相继作8位CRC校验
输入参数:
chCurrByte低8位数据有效,记录了上一次CRC校验的余数
chNextByte低8位数据有效,记录了本次要继续校验的一个字节
传出参数:
{
if (file.tellg() >= nFileEnd) //到文件末尾,退出循环
{
bParseCont = false;
Βιβλιοθήκη Baidubreak;
}
//看当前字符是不是0xaa,如果不是,则重新寻找7个连续的0xaa
if (file.get() != 0xaa)
{
i = -1;
(2)捕捉并分析局域网上的所有ethernetbroadcast帧进行分析。
(3)捕捉局域网上的所有ethernetmulticast帧进行分析。
实验环境:安装好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字节的前导字)。
//输出目的地址,并校验
cout << endl << "目的地址:\t";
for (i = 0; i < 6; i++) //输出格式为:xx-xx-xx-xx-xx-xx
{
c = file.get();
cout.width(2);
cout<< hex << c << dec << (i==5 ? "" : "-");
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字节的长度;所幸的是,后者定义的有效长度值与前者定义的有效类型值无一相同,这样就容易区分两种帧格式
{
//检测剩余文件是否可能包含完整帧头
if (file.tellg() + 14 > nFileEnd)
{
cout<<endl<<"没有找到完整帧头,解析终止"<<endl;
file.close();
exit(0);
}
int c; //读入字节
int i = 0; //循环控制变量
int EtherType = 0; //由帧中读出的类型字段
checkCRC(nCheck,c); // CRC校验
EtherType <<= 8; //转换成主机格式
EtherType |= c;
//定位下一个帧,以确定当前帧的结束位置
while ( bParseCont )
{
for (int i = 0; i < 7; i++) //找下一个连续的7个0xaa
{
c = file.get();
cout.width(2);
cout<< hex << c << dec << (i==5 ? "" : "-");
checkCRC(nCheck, c); //继续校验
}
//输出类型字段,并校验
cout<<endl<<"类型字段:\t";
cout.width(2);
实验一Ethernet帧结构解析
一.需求分析
实验目的:(1)掌握Ethernet帧各个字段的含义与帧接收过程;
(2)掌握Ethernet帧解析软件设计与编程方法;
(3)掌握Ethernet帧CRC校验算法原理与软件实现方法。
实验任务:(1)捕捉任何主机发出的Ethernet802.3格式的帧和DIXEthernetV2(即Ethernet II)格式的帧并进行分析。
{
break;
}
}
//将数据字段偏移量定位在上述二进制串之后14字节处,并准备进入解析阶段
nCurrDataOffset = file.tellg() + 14;
file.seekg(-8,ios::cur);
//主控循环
while ( bParseCont ) //当仍然可以继续解析输入文件时,继续解析
4.主函数的设计:
void main(int argc, char* argv[])
{
//检测命令行参数的正确性
if (argc != 2)
{
cout << "请以帧封装包文件为参数重新执行程序" << endl;
exit(0);
}
//检测输入文件是否存在,并可以按所需的权限和方式打开
ifstream file(argv[1], ios::in|ios::binary|ios::nocreate);
}
else //首位为0,只移位,不进行异或运算
{
chCurrByte <<= 1; //移一位
if ( (chNextByte & nMask) != 0) //补一位
{
chCurrByte |= 1;
}
}
}
}
2.部分变量的声明:
int nSN = 1; //帧序号
int nCheck = 0; //校验码
chCurrByte低8位数据有效,记录了本次CRC校验的余数
void checkCRC(int &chCurrByte, int chNextByte)
{
// CRC循环:每次调用进行8次循环,处理一个字节的数据。
for (int nMask = 0x80; nMask > 0; nMask >>= 1)
int nCurrDataLength = 0; //数据字段长度
bool bParseCont = true; //是否继续对输入文件进行解析
int nFileEnd = 0; //输入文件的长度
//计算输入文件的长度
file.seekg(0, ios::end); //把文件指针移到文件的末尾
nFileEnd = file.tellg(); //取得输入文件的长度
int nCurrDataOffset = 22; //帧头偏移量
int nCurrDataLength = 0; //数据字段长度
bool bParseCont = true; //是否继续对输入文件进行解析
int nFileEnd = 0; //输入文件的长度
3.计算数据段的长度:
nCurrDataLength =
while ( true )
{
for (int j = 0; j < 7; j++) //找7个连续的0xaa
{
if (file.tellg() >= nFileEnd) //安全性检测
{
cout<<"没有找到合法的帧"<<endl;
file.close();
exit(0);
}
//看当前字符是不是0xaa,如果不是,则重新寻找7个连续的0xaa
//输出类型字段的高8位
c = file.get();
cout<< hex << c << dec << " ";
checkCRC(nCheck, c); // CRC校验
EtherType = c;
//输出类型字段的低8位
c = file.get();
cout.width(2);
cout<< hex << c;
if (file.get() != 0xaa)
{
j = -1;
}
}
if (file.tellg() >= nFileEnd) //安全性检测
{
cout<<"没有找到合法的帧"<<endl;
file.close();
exit(0);
}
if (file.get() == 0xab) //判断7个连续的0xaa之后是否为0xab
帧格式Ethernet II和IEEE802.3的帧格式分别如下。
EthernetrII帧格式:
----------------------------------------------------------------------------------------------
|前序|目的地址|源地址|类型|数据
bParseCont ? //是否到达文件末尾
(file.tellg() - 8 - 1 - nCurrDataOffset) : //没到文件末尾:下一帧头位置-前导码和定界符长度- CRC校验码长度-数据字段起始位置
(file.tellg() - 1 - nCurrDataOffset); //已到达文件末尾:文件末尾位置- CRC校验码长度-数据字段起始位置
| FCS |
----------------------------------------------------------------------------------------------
| 8 byte | 6 byte | 6 byte | 2 byte | 46~1500 byte | 4 byte|
相关文档
最新文档