Ethernet帧结构解析.docx

上传人:b****8 文档编号:9530339 上传时间:2023-02-05 格式:DOCX 页数:16 大小:199.47KB
下载 相关 举报
Ethernet帧结构解析.docx_第1页
第1页 / 共16页
Ethernet帧结构解析.docx_第2页
第2页 / 共16页
Ethernet帧结构解析.docx_第3页
第3页 / 共16页
Ethernet帧结构解析.docx_第4页
第4页 / 共16页
Ethernet帧结构解析.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

Ethernet帧结构解析.docx

《Ethernet帧结构解析.docx》由会员分享,可在线阅读,更多相关《Ethernet帧结构解析.docx(16页珍藏版)》请在冰豆网上搜索。

Ethernet帧结构解析.docx

Ethernet帧结构解析

实验一Ethernet帧结构解析

一.需求分析

实验目的:

(1)掌握Ethernet帧各个字段的含义与帧接收过程;

(2)掌握Ethernet帧解析软件设计与编程方法;

(3)掌握Ethernet帧CRC校验算法原理与软件实现方法。

实验任务:

(1)捕捉任何主机发出的Ethernet802.3格式的帧和DIXEthernetV2(即EthernetII)格式的帧并进行分析。

(2)捕捉并分析局域网上的所有ethernetbroadcast帧进行分析。

(3)捕捉局域网上的所有ethernetmulticast帧进行分析。

实验环境:

安装好Windows2000Server操作系统+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字节的前导字)。

帧格式EthernetII和IEEE802.3的帧格式分别如下。

EthernetrII帧格式:

----------------------------------------------------------------------------------------------

|前序|目的地址|源地址|类型|数据

|FCS|

----------------------------------------------------------------------------------------------

|8byte|6byte|6byte|2byte|46~1500byte|4byte|

IEEE802.3一般帧格式

-----------------------------------------------------------------------------------------------------------|前序|帧起始定界符|目的地址|源地址|长度|数据|FCS|-----------------------------------------------------------------------------------------------------------|7byte|1byte|2/6byte|2/6byte|2byte|46~1500byte|4byte|EthernetII和IEEE802.3的帧格式比较类似,主要的不同点在于前者定义的2字节的类型,而后者定义的是2字节的长度;所幸的是,后者定义的有效长度值与前者定义的有效类型值无一相同,这样就容易区分两种帧格式

2程序流程图:

三.详细设计:

1.CRC校验部分设计:

为了对以太网帧的对错进行检验,需要设计CRC校验部分。

采用以为相与的方式对帧的首部相继作8位CRC校验

输入参数:

chCurrByte低8位数据有效,记录了上一次CRC校验的余数

chNextByte低8位数据有效,记录了本次要继续校验的一个字节

传出参数:

chCurrByte低8位数据有效,记录了本次CRC校验的余数

voidcheckCRC(int&chCurrByte,intchNextByte)

{

//CRC循环:

每次调用进行8次循环,处理一个字节的数据。

for(intnMask=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.部分变量的声明:

intnSN=1;//帧序号

intnCheck=0;//校验码

intnCurrDataOffset=22;//帧头偏移量

intnCurrDataLength=0;//数据字段长度

boolbParseCont=true;//是否继续对输入文件进行解析

intn=0;//输入文件的长度

3.计算数据段的长度:

nCurrDataLength=

bParseCont?

//是否到达文件末尾

(()-8-1-nCurrDataOffset):

//没到文件末尾:

下一帧头位置-前导码和定界符长度-CRC校验码长度-数据字段起始位置

(()-1-nCurrDataOffset);//已到达文件末尾:

文件末尾位置-CRC校验码长度-数据字段起始位置

4.主函数的设计:

voidmain(intargc,char*argv[])

{

//检测命令行参数的正确性

if(argc!

=2)

{

cout<<"请以帧封装包文件为参数重新执行程序"<

exit(0);

}

//检测输入文件是否存在,并可以按所需的权限和方式打开

ifstream[1],ios:

:

in|ios:

:

binary|ios:

:

nocreate);

if(!

())

{

cout<<"无法打开帧封装包文件,请检查文件是否存在并且未损坏"<

exit(0);

}

//变量声明及初始化

intnSN=1;//帧序号

intnCheck=0;//校验码

intnCurrDataOffset=22;//帧头偏移量

intnCurrDataLength=0;//数据字段长度

boolbParseCont=true;//是否继续对输入文件进行解析

intn=0;//输入文件的长度

//计算输入文件的长度

(0,ios:

:

end);//把文件指针移到文件的末尾

n=();//取得输入文件的长度

(0,ios:

:

beg);//文件指针位置初始化

cout.fill('0');//显示初始化

cout.setf(ios:

:

uppercase);//以大写字母输出

//定位到输入文件中的第一个有效帧

//从文件头开始,找到第一个连续的“AA-AA-AA-AA-AA-AA-AA-AB”

while(true)

{

for(intj=0;j<7;j++)//找7个连续的0xaa

{

if(()>=n)//安全性检测

{

cout<<"没有找到合法的帧"<

();

exit(0);

}

//看当前字符是不是0xaa,如果不是,则重新寻找7个连续的0xaa

if(()!

=0xaa)

{

j=-1;

}

}

if(()>=n)//安全性检测

{

cout<<"没有找到合法的帧"<

();

exit(0);

}

if(()==0xab)//判断7个连续的0xaa之后是否为0xab

{

break;

}

}

//将数据字段偏移量定位在上述二进制串之后14字节处,并准备进入解析阶段

nCurrDataOffset=()+14;

(-8,ios:

:

cur);

//主控循环

while(bParseCont)//当仍然可以继续解析输入文件时,继续解析

{

//检测剩余文件是否可能包含完整帧头

if(()+14>n)

{

cout<

();

exit(0);

}

intc;//读入字节

inti=0;//循环控制变量

intEtherType=0;//由帧中读出的类型字段

boolbAccept=true;//是否接受该帧

//输出帧的序号

cout<

\t\t"<

//输出前导码,只输出,不校验

cout<

\t";

for(i=0;i<7;i++)//输出格式为:

AAAAAAAAAAAAAA

{

cout.width

(2);

cout<

}

//输出帧前定界符,只输出,不校验

cout<

\t";

cout.width

(2);//输出格式为:

AB

cout<

//输出目的地址,并校验

cout<

\t";

for(i=0;i<6;i++)//输出格式为:

xx-xx-xx-xx-xx-xx

{

c=();

cout.width

(2);

cout<

"":

"-");

if(i==0)//第一个字节,作为“余数”等待下一个bit

{

nCheck=c;

}

else//开始校验

{

checkCRC(nCheck,c);

}

}

//输出源地址,并校验

cout<

\t";

for(i=0;i<6;i++)//输出格式为:

xx-xx-xx-xx-xx-xx

{

c=();

cout.width

(2);

cout<

"":

"-");

checkCRC(nCheck,c);//继续校验

}

//输出类型字段,并校验

cout<

\t";

cout.width

(2);

//输出类型字段的高8位

c=();

cout<

checkCRC(nCheck,c);//CRC校验

EtherType=c;

//输出类型字段的低8位

c=();

cout.width

(2);

cout<

checkCRC(nCheck,c);//CRC校验

EtherType<<=8;//转换成主机格式

EtherType|=c;

//定位下一个帧,以确定当前帧的结束位置

while(bParseCont)

{

for(inti=0;i<7;i++)//找下一个连续的7个0xaa

{

if(()>=n)//到文件末尾,退出循环

{

bParseCont=false;

break;

}

//看当前字符是不是0xaa,如果不是,则重新寻找7个连续的0xaa

if(()!

=0xaa)

{

i=-1;

}

}

//如果直到文件结束仍没找到上述比特串,将终止主控循环的标记bParseCont置为true

bParseCont=bParseCont&&(()

//判断7个连续的0xaa之后是否为0xab

if(bParseCont&&()==0xab)

{

break;

}

}

//计算数据字段的长度

nCurrDataLength=

bParseCont?

//是否到达文件末尾

(()-8-1-nCurrDataOffset):

//没到文件末尾:

下一帧头位置-前导码和定界符长度-CRC校验码长度-数据字段起始位置

(()-1-nCurrDataOffset);//已到达文件末尾:

文件末尾位置-CRC校验码长度-数据字段起始位置

//以文本格式数据字段,并校验

cout<

\t";

unsignedchar*pData=newunsignedchar[nCurrDataLength];//创建缓冲区

(bParseCont?

(-8-1-nCurrDataLength):

(-1-nCurrDataLength),ios:

:

cur);

(pData,nCurrDataLength);//读入数据字段

intnCount=50;//每行的基本字符数量

for(i=0;i

{

nCount--;

cout<

checkCRC(nCheck,(int)pData[i]);//CRC校验

if(nCount<0)//换行处理

{

//将行尾的单词写完整

if(pData[i]=='')

{

cout<

nCount=50;

}

//处理过长的行尾单词:

换行并使用连字符

if(nCount<-10)

{

cout<<"-"<

nCount=50;

}

}

}

delete[]pData;//释放缓冲区空间

//输出CRC校验码,如果CRC校验有误,则输出正确的CRC校验码

cout<

c=();//读入CRC校验码

intnTmpCRC=nCheck;

checkCRC(nCheck,c);//最后一步校验

if((nCheck&0xff)==0)//CRC校验无误

{

cout.width

(2);

cout<<"(正确):

\t"<

}

else//CRC校验有误

{

cout.width

(2);

cout<<"(错误):

\t"<

checkCRC(nTmpCRC,0);//计算正确的CRC校验码

cout<<"\t应为:

"<

bAccept=false;//将帧的接收标记置为false

}

//如果数据字段长度不足46字节或数据字段长度超过1500字节,则将帧的接收标记置为false

if(nCurrDataLength<46||nCurrDataLength>1500)

{

bAccept=false;

}

//输出帧的接收状态

cout<

\t\t"<<(bAccept?

"Accept":

"Discard")<

nSN++;//帧序号加1

nCurrDataOffset=()+22;//将数据字段偏移量更新为下一帧的帧头结束位置

}

//关闭输入文件

();

}

四.运行结果:

五.简明用户手册:

用户需将源程序在VC++6.0下运行成功后,将实验1.EXE放在DOS下运行,运行的同时需要输入位置参数,本例用的位置参数为input,回车即可。

六.实验总结:

这次试验,充分运用了所学的计算机网络知识,设计出了如何解析以太网帧,从而更加深刻的了解到了以太网帧的结构及其的相关问题。

其实通过这些最近的实验觉得最重要一点就是:

我们一定要自己动手,这样才能真正的学到东西。

书本知识固然重要,但我们更要学会将书本知识应用到实际的工作中。

实践中才会发现错误,也才能改进,才能达到学习的最终目的。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1