51单片机简单Ping的实现Word格式文档下载.docx
- 文档编号:16412555
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:8
- 大小:19.86KB
51单片机简单Ping的实现Word格式文档下载.docx
《51单片机简单Ping的实现Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《51单片机简单Ping的实现Word格式文档下载.docx(8页珍藏版)》请在冰豆网上搜索。
总之,经过简化的ping能够完成最基本的连通测试功能。
0
8
16
31
------------------------------------------------
|类型(8或0)|代码(0)|
校验和
|
|
标识符
序号
可选数据
。
。
图1ICMP回送请求或回答报文格式
PingCycle
|定时操作
V
PingCmd
----------------
--------------
-------->
|
PingRequest|----------->
命令
请求
A
B
<
--------|PingEcho
|<
-----------|PingAnswer
回显
应答
图2APingB过程(全双工操作,反过来亦可,未画出反向过程)
图1所示为ICMP回送请求/回答报文格式(即Ping包格式),在实现网卡驱动程序后,Ping的实现简化为填写报文(详见伪代码清单)。
如图2所示,完整ping过程我主要用4个函数实现。
Ping请求(PingRequest)、Ping应答(PingAnswer)、收到应答后回显(PingEcho)、定时操作(PingCycle)。
PingRequest完成Ping请求。
当输入Ping命令后,调用此函数,发出请求包。
PingAnswer完成Ping应答。
它工作在后台,每当收到发给自己IP的请求包就自动应答。
PingEcho显示应答信息。
每当收到应答就立即显示相关信息。
PingCycle定时操作pingbuf记录缓冲区。
每秒钟扫描一次,并根据当前情况和状态进行状态变迁。
-----------------------------------------------------
||状态(status)|次数(times)|内存句柄(memhandle)|
|----------------------------------------------------
N个|
N=MaxLenPingBuf
图3pingbuf记录缓冲区格式
IP地址要先转换成MAC地址才能在以太网上传输,如果ARP缓存里没有对应项,则需要较长时间查找(网络传输时间相对于CPU时间)。
为了不阻塞进程,我设计了一个pingbuf记录缓冲区,如图3所示。
此表1秒钟被查询一次,根据当前情况改变状态。
它包括状态、次数、内存句柄三个域。
“次数”字段指示测试剩余数,为0表示测完,同时改变状态为0以表明此记录项现在空闲。
“内存句柄”字段保存ICMP报文缓冲区首址指针。
“状态”字段记录状态号,含义如下:
0---空闲
1---已发出但无应答
2---已发出且应答
3---等ARP
4---第一次准备发(用于同步1秒时钟)
状态变迁图如图4所示。
图4略,详见伪代码清单PingCycle,请自行画出状态图。
这个实现里还使用了ping命令处理、IP地址转换、校验和计算等辅助程序,详见伪代码清单。
IP协议使用统一的CheckSum算法计算和验证数据报的首部校验和。
将首部视为一个16位的整数序列,并定义校验和是首部中所有16位整数的和的二进制反码。
同样和数及补码也被定义使用二进制反码算法。
所有TCP/IP协议的校验和计算和数据包的校验均由CheckSum子程序完成。
不过需要注意的是TCP和UDP的校验需要加上伪头部。
需要首部校验和计算及验证的包为:
IP、ICMP、UDP、TCP。
相互间的差别仅在于求和数据不同,算法都采用CheckSum。
详见源程序清单。
(提示:
IP包头从版本号、首部长度、服务类型到目的站IP地址(如果不含IP选项)共20字节;
ICMP校验和只覆盖ICMP报文。
对比UDP、TCP伪首部和IP首部相似点,可以不必单独分配伪首部缓冲区,而直接利用IP缓冲区计算校验和。
观察知IP头邻接数据,采取一定措施可实现直接计算。
即先将IP寿命字段清0,协议字段赋相应值,校验和赋UDP/TCP包长度值,并加上12,表示伪首部的3长字长度,完成计算后向IP包首部添入正确寿命、校验和值,见图5。
)
31
----------------------------
---------------------------
|寿命|协议|首部校验和|
源站IP地址
---------------------------
目的站IP地址
|零|协议|UDP/TCP长度|
数据
UDP/TCP包数据
IP包格式(局部)
UDP、TCP伪首部+数据格式
图5IP包格式(局部)和UDP、TCP伪首部格式对比图
伪代码清单:
PingRequest(IP地址)
//Ping请求
{
//申请小号内存
pICMP=OSMemGet();
//填写以太网帧
目的MAC地址=ping命令传入的IP地址解析后得到的物理地址
源MAC地址=本节点MAC地址
类型=0x0800
//IP包
//填写IP帧
版本号&
首部长度=0x45
服务类型=0
总长度=60
标识符=GlobalID++
//全局变量16位GlobalID加1
标志&
分片偏移量=0x0000
寿命=0x80
协议=0x0001
//icmp
首部校验和=0x0000
源IP地址=本节点IP地址
目的IP地址=ping命令传入的IP地址
首部校验和=CheckSum(IP首部和长度)
//计算IP包首部校验和
//填写ICMP帧
类型=8
//8请求
0应答
代码=0
校验和=0x0
标识符=0x0300
序号=GlobalID
校验和=CheckSum(ICMP首部和长度)
//计算ICMP包首部校验和
//将ICMP包登记在PingBuf中
for(i=0;
i<
MaxLenPingBuf;
i++){
if(PingBuf[i].status==0){
PingBuf[i].times=0x8;
//测试8次
PingBuf[i].ip=ping命令传入的IP地址;
PingBuf[i].memhandle=内存句柄;
PingBuf[i].status=4;
//第一次准备发(用于同步1秒时钟)
break;
}
if(i==MaxLenPingBuf)释放内存;
}
PingAnswer(*输入包缓冲区首址pBUF)
//Ping应答
{
//改写以太网帧
目的MAC地址=源MAC地址
//改写IP帧
寿命=寿命-1
目的IP地址=源IP地址
//改写ICMP帧
类型=0
//直接发送ICMP包至TxQFIFO缓存
OSQSend(QID,*pBUF);
PingEcho(*输入包缓冲区首址pBUF)
//收到应答后回显
//打印ping响应,因为51定时器较慢,time参数省略(time是本机与对方主机往返一次所用时间)。
PrintStr("
\n\tReplyfromIP="
);
PrintStr(输入包之源IP地址);
:
bytes=32"
TTL="
PrintByte(输入包之TTL);
\n"
//处理PingBuf的记录
if(PingBuf[i].status==1){
if(PingBuf[i].ip==pBUF.ipframe.ip){
PingBuf[i].status=2;
//已发出且应答
PingCycle()
//定时操作,放在1秒循环任务中
for(;
;
){
taskDelay(1秒);
switch(PingBuf[i].status)
case0:
//空闲
{
case1:
//已发出但无应答
//打印超时信息
\n\tRequesttimedout.("
PrintStr(PingBuf[i].ip);
)\n"
case2:
//状态变迁
PingBuf[i].times=PingBuf[i].times-1;
if(PingBuf[i].times==0)
PingBuf[i].status=0;
else{
case4:
//查ARP缓存
if(ARP缓存有对应项){
PingBuf[i].status=1;
elsePingBuf[i].status=3;
//等ARP
}
case3:
if(ARP缓存有对应项){
default:
//其他状态,错误
voidPingCommand(WORDTABLE*WordTable)//PING命令处理
if(WordTable->
Num==1)
\nPleaseinputIPaddress!
\n\n"
if(IPadrToHEX(WordTable->
wt[1].Str,&
ping_ip_address)==0){
\nIPaddresserror!
return;
else
PingRequest(ping_ip_address);
INT16UCheckSum(INT16U*buf,INT16Ulength)
//校验和计算
INT16Ulen;
INT32Usum;
len=length>
>
1;
for(sum=0;
len>
0;
len--)
sum+=*buf++;
if(length&
1)
sum+=(*buf&
0xFF00);
sum=(sum>
16)+(sum&
0xFFFF);
sum+=(sum>
16);
return(~sum);
unionip_address_type{
//ip地址数据结构
unsignedlongdwords;
unsignedintwords[2];
unsignedcharbytes[4];
};
bitIPadrToHEX(unsignedchar*Str,unionip_address_type*ip)
//IP字符串转换到IP地址值
unsignedchari,j,ch,x;
ch=*Str++;
for(j=0;
j<
3;
j++){
x=0;
4;
if(ch=='
.'
){ch=*Str++;
break;
elseif(i==3)return0;
elseif(ch<
0&
&
ch>
9)return0;
x=10*x+(ch-'
0'
ip->
bytes[j]=x;
\0'
bytes[3]=x;
return1;
voidHEXToIPadr(unsignedchar*Str,unionip_address_type*ip)
//IP地址值转换到IP字符串
unsignedchari;
unsignedcharx,y;
x=ip->
bytes[i];
if(x>
99){
y=x/100;
*Str++=y+'
x=x-100*y;
y=x/10;
x=x-10*y;
*Str++=x+'
if(i==3)*Str++='
else*Str++='
elseif(x>
9){
y=x/10;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 51 单片机 简单 Ping 实现
![提示](https://static.bdocx.com/images/bang_tan.gif)