Ethernet帧结构解析汇报文档格式.docx
《Ethernet帧结构解析汇报文档格式.docx》由会员分享,可在线阅读,更多相关《Ethernet帧结构解析汇报文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
所幸的是,后者定义的有效长度值与前者定义的有效类型值无一相同,这样就容易区分两种帧格式
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;
>
=1)
if((chCurrByte&
0x80)!
=0)//首位为1:
移位,并进行异或运算
{
chCurrByte<
<
=1;
//移一位
if((chNextByte&
nMask)!
=0)//补一位
{
chCurrByte|=1;
}
chCurrByte^=7;
//首位已经移出,仅对低8位进行异或运算,7的二进制为0000,0111
else//首位为0,只移位,不进行异或运算
}
2.部分变量的声明:
intnSN=1;
//帧序号
intnCheck=0;
//校验码
intnCurrDataOffset=22;
//帧头偏移量
intnCurrDataLength=0;
//数据字段长度
boolbParseCont=true;
//是否继续对输入文件进行解析
intnFileEnd=0;
//输入文件的长度
3.计算数据段的长度:
nCurrDataLength=
bParseCont?
//是否到达文件末尾
(file.tellg()-8-1-nCurrDataOffset):
//没到文件末尾:
下一帧头位置-前导码和定界符长度-CRC校验码长度-数据字段起始位置
(file.tellg()-1-nCurrDataOffset);
//已到达文件末尾:
文件末尾位置-CRC校验码长度-数据字段起始位置
4.主函数的设计:
voidmain(intargc,char*argv[])
//检测命令行参数的正确性
if(argc!
=2)
cout<
"
请以帧封装包文件为参数重新执行程序"
<
endl;
exit(0);
//检测输入文件是否存在,并可以按所需的权限和方式打开
ifstreamfile(argv[1],ios:
:
in|ios:
binary|ios:
nocreate);
if(!
file.is_open())
无法打开帧封装包文件,请检查文件是否存在并且未损坏"
//变量声明及初始化
//计算输入文件的长度
file.seekg(0,ios:
end);
//把文件指针移到文件的末尾
nFileEnd=file.tellg();
//取得输入文件的长度
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(file.tellg()>
=nFileEnd)//安全性检测
cout<
"
没有找到合法的帧"
endl;
file.close();
//看当前字符是不是0xaa,如果不是,则重新寻找7个连续的0xaa
if(file.get()!
=0xaa)
j=-1;
if(file.get()==0xab)//判断7个连续的0xaa之后是否为0xab
break;
//将数据字段偏移量定位在上述二进制串之后14字节处,并准备进入解析阶段
nCurrDataOffset=file.tellg()+14;
file.seekg(-8,ios:
cur);
//主控循环
while(bParseCont)//当仍然可以继续解析输入文件时,继续解析
//检测剩余文件是否可能包含完整帧头
if(file.tellg()+14>
nFileEnd)
endl<
没有找到完整帧头,解析终止"
intc;
//读入字节
inti=0;
//循环控制变量
intEtherType=0;
//由帧中读出的类型字段
boolbAccept=true;
//是否接受该帧
//输出帧的序号
endl<
序号:
\t\t"
nSN;
//输出前导码,只输出,不校验
前导码:
\t"
;
for(i=0;
i<
i++)//输出格式为:
AAAAAAAAAAAAAA
cout.width
(2);
hex<
file.get()<
dec<
//输出帧前定界符,只输出,不校验
帧前定界符:
//输出格式为:
AB
file.get();
//输出目的地址,并校验
目的地址:
6;
xx-xx-xx-xx-xx-xx
c=file.get();
c<
(i==5?
:
-"
if(i==0)//第一个字节,作为“余数”等待下一个bit
nCheck=c;
else//开始校验
checkCRC(nCheck,c);
//输出源地址,并校验
源地址:
//继续校验
//输出类型字段,并校验
类型字段:
//输出类型字段的高8位
//CRC校验
EtherType=c;
//输出类型字段的低8位
c;
checkCRC(nCheck,c);
EtherType<
=8;
//转换成主机格式
EtherType|=c;
//定位下一个帧,以确定当前帧的结束位置
while(bParseCont)
for(inti=0;
i++)//找下一个连续的7个0xaa
=nFileEnd)//到文件末尾,退出循环
bParseCont=false;
=0xaa)
i=-1;
//如果直到文件结束仍没找到上述比特串,将终止主控循环的标记bParseCont置为true
bParseCont=bParseCont&
&
(file.tellg()<
nFileEnd);
//判断7个连续的0xaa之后是否为0xab
if(bParseCont&
file.get()==0xab)
//计算数据字段的长度
nCurrDataLength=
bParseCont?
(file.tellg()-8-1-nCurrDataOffset):
(file.tellg()-1-nCurrDataOffset);
//以文本格式数据字段,并校验
数据字段:
unsignedchar*pData=newunsignedchar[nCurrDataLength];
//创建缓冲区
file.seekg(bParseCont?
(-8-1-nCurrDataLength):
(-1-nCurrDataLength),ios:
file.read(pData,nCurrDataLength);
//读入数据字段
intnCount=50;
//每行的基本字符数量
nCurrDataLength;
i++)//输出数据字段文本
nCount--;
pData[i];
//字符输出
checkCRC(nCheck,(int)pData[i]);
if(nCount<
0)//换行处理
//将行尾的单词写完整
if(pData[i]=='
'
)
nCount=50;
//处理过长的行尾单词:
换行并使用连字符
-10)
delete[]pData;
//释放缓冲区空间
//输出CRC校验码,如果CRC校验有误,则输出正确的CRC校验码
CRC校验"
//读入CRC校验码
intnTmpCRC=nCheck;
//最后一步校验
if((nCheck&
0xff)==0)//CRC校验无误
(正确):
else//CRC校验有误
(错误):
checkCRC(nTmpCRC,0);
//计算正确的CRC校验码
\t应为:
(nTmpCRC&
0xff);
bAccept=false;
//将帧的接收标记置为false
//如果数据字段长度不足46字节或数据字段长度超过1500字节,则将帧的接收标记置为false
if(nCurrDataLength<
46||nCurrDataLength>
1500)
//输出帧的接收状态
状态:
(bAccept?
Accept"
Discard"
)<
nSN++;
//帧序号加1
nCurrDataOffset=file.tellg()+22;
//将数据字段偏移量更新为下一帧的帧头结束位置
//关闭输入文件
file.close();
四.运行结果:
五.简明用户手册:
用户需将源程序在VC++6.0下运行成功后,将实验1.EXE放在DOS下运行,运行的同时需要输入位置参数,本例用的位置参数为input,回车即可。
六.实验总结:
这次试验,充分运用了所学的计算机网络知识,设计出了如何解析以太网帧,从而更加深刻的了解到了以太网帧的结构及其的相关问题。
其实通过这些最近的实验觉得最重要一点就是:
我们一定要自己动手,这样才能真正的学到东西。
书本知识固然重要,但我们更要学会将书本知识应用到实际的工作中。
实践中才会发现错误,也才能改进,才能达到学习的最终目的。