【LwIP】让LwIP拥有PING其他设备的能力_lwip ping-程序员宅基地

技术标签: STM32  

本文的前提是单片机的LWIP已经跑起来了,能够被外部设备ping通,在此基础上,新增让单片机ping外部设备的功能。

首先,我们需要创建ICMP控制块,在主循环前创建一次即可。

struct raw_pcb *ping_pcb;
uint8_t icmp_pcb_init(void)
{
	ping_pcb = raw_new(IP_PROTO_ICMP);//创建ICMP控制块
	if(!ping_pcb)
		return 1;
	return 0;
}

然后,我们需要构建ping包,用于ping外部设备。

uint8_t ping_send(void)
{
	struct pbuf *p;
	struct ip_addr ipaddr;
	struct icmp_echo_hdr *iecho;
	err_t err;
	
	IP4_ADDR(&ipaddr, 192, 168,  0, 1);//在这里改成你单片机的IP地址,我这里假设本机IP是192.168.0.1
	ip_addr_set(&ping_pcb->local_ip, &ipaddr);//本机IP
	
	IP4_ADDR(&ipaddr, 192, 168, 0, 2);//在这里改成你想ping的IP地址,我这里假设想ping的IP地址是192.168.0.2
	ip_addr_set(&ping_pcb->remote_ip, &ipaddr);//远端IP
	
	p = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr), PBUF_RAM);
	if(!p)
	{
		return 1;
	}

	iecho = (struct icmp_echo_hdr *)p->payload;
	iecho->type = 8;
	iecho->code = 0;
	iecho->id =htons(0x0200);
	iecho->seqno =htons(0x5800); 
	iecho->chksum = 0;
	//iecho->chksum = inet_chksum(p->payload, sizeof(struct icmp_echo_hdr));//这里需要注释掉,否则会ping失败
	
	err = raw_sendto(ping_pcb, p, &ping_pcb->remote_ip);//发送ping包
	if( err != ERR_OK )
	{
		return 1;
	}
	pbuf_free(p);

	return 0;
}

其次,当我们的ping包发送出去以后,如何接收ping的应答包呢?因此,需要在LWIP的icmp.c文件中修改一下代码。
void icmp_input(struct pbuf *p, struct netif *inp)函数前面创建一个全局变量,用于标记接收到了ping的应答包。

volatile unsigned char pingEchoReply = 0;

void icmp_input(struct pbuf *p, struct netif *inp)函数里面的switch语句中,手动添加一个“case ICMP_ER”(ICMP Echo Reply)的判断条件,让设备能够接受处理icmp的回复消息。如下:

  case ICMP_ER:	
		pingEchoReply = 1;//这里只做一个标记,简答地表示接收到了ping的应答包
		break;

最后,就可以让单片机ping外部设备了。

#include "lwip/raw.h"
#include "lwip/icmp.h"
#include "lwip/arch.h"
#include "lwip/ip_addr.h"
extern unsigned char pingEchoReply;
int main(void)
{
	/*...各种你需要的初始化...*/
	icmp_pcb_init();//创建ICMP控制块
	while(1)
	{
		ping_send();//发送ping包
		while(pingEchoReply==0);//等待ping应答
		if(pingEchoReply==1)
		{
			pingEchoReply = 0;
			//说明ping成功,可以做你想做的事
		}
	}
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_22902757/article/details/92798180

智能推荐

[FAQ08836]如何调试malloc(堆越界)问题-程序员宅基地

[DESCRIPTION]有一类NE比较特殊,就是堆引起的异常(调用malloc申请的内存后使用不当引起的异常):1. 申请后多次释放 (double free)2. 释放后又去使用 (used after free)3. 使用越界 (比如申请了50节内存,结果在使用时多用了8字节的内存,这样就把后面的内存的内容踩坏,引起堆结构异常)4. 释放时传给free()的地址不是mal

【Android基础】Android SQLite存储自定义对象-程序员宅基地

Android SQLite存储自定义对象在SQLite数据库中可存储的数据类型有NULL、INTEGER、REAL(浮点型)、TEXT、BOOL,一共是五种数据类型。在Android开发中,我们存储数据的一般的作法是数据库的属性就是类的成员变量,比如: 要存储一个人的姓名和年龄,在类中的是将它们定义为两个成员变量class Person{ private String name;

C++程序员面试宝典——基本概念易错题-程序员宅基地

1. C中printf计算参数时,是从右到左压栈。printf("%d, %d\n", *ptr, ++*ptr)2. 与运算计算时,第一个不符合则不对第二个进行判断。或运算计算时,第一个符合则不对第二个进行计算。for(a=0,x=0; a3. if('A'==a) 比if(a=='A')好,因为写错成“=”可以检测出来。4. float a=1.0; cout5. 32位机器上

Linux内核分析:页回收导致的cpu load瞬间飙高的问题分析与思考--------------蘑菇街技术博客...-程序员宅基地

http://mogu.io/156-156摘要本文一是为了讨论在Linux系统出现问题时我们能够借助哪些工具去协助分析,二是讨论出现问题时大致的可能点以及思路,三是希望能给应用层开发团队介绍一些Linux内核机制从而选择更合适的使用策略。前言搜索团队的服务器前段时间频繁出现CPU load很高(比如load average达到80多)的情况,正所谓术业有专攻,搜索的兄弟们对L..._没有合入主线的 内核patch

Latex去掉默认的段首空格_latex段前强制空格如歌处理-程序员宅基地

两种方法:第一种方法,是全局的操作。比如:若放在第一段的段首,则下面所有的段落都会按照这个格式缩进。 \setlength{\parindent}{0pt}第二种方法,就是针对某一段,比较实用的,需要缩进哪段就直接放在段首就OK了\noindent..._latex段前强制空格如歌处理

Ubuntu系统安装分区设置_ubuntu系统分区设置-程序员宅基地

1. 创建主分区:主分区,用于存放系统20G 主分区 空间起始位置 Ext4日志文件系统 /2. 创建swap分区:逻辑分区、大小设置为电脑内存大小,2G;2048MB 逻辑分区 空间起始位置 交换空间3. 创建boot分区:引导分区,通常设置成200M200MB 逻辑分区 空间起始位置 ..._ubuntu系统分区设置

随便推点

[剑指-Offer] 37. 序列化二叉树(层序遍历、前序遍历、递归、特殊情况)_层序遍历可以得到唯一的二叉树吗-程序员宅基地

文章目录1. 题目来源2. 题目说明3. 题目解析方法一:层序遍历+迭代解法不好的解法1不好的解法2成功版方法二:先序遍历+递归解法1. 题目来源链接:序列化二叉树来源:LeetCode——《剑指-Offer》专项2. 题目说明请实现两个函数,分别用来序列化和反序列化二叉树。示例:你可以将以下二叉树: 1 / \ 2 3 / \..._层序遍历可以得到唯一的二叉树吗

selenium连接浏览器方式-程序员宅基地

支持HtmlUnitDriver无头浏览器自动化selenium运行Chrome需要chromeDriver定位元素的方式:是可嵌套的WebElement cheese = driver.findElement(By.id("cheese"));WebElement cheddar = cheese.findElement(By.id("cheddar"));..._selenium webdriver 通过什么方式本地接口调用浏览器

解决Redhat 7 ambari安装hadoop过程中出现myql安装出错_ambari部署hadoop集群时mysql server install失败-程序员宅基地

[linux]centos7下解决yum install mysql-server没有可用包第一步:安装从网上下载文件的wget命令[root@master ~]# yum -y install wget第二步:下载mysql的repo源[root@master ~]# wget http://repo.mysql.com/mysql-community-release-el7-5.noarch...._ambari部署hadoop集群时mysql server install失败

ArcGIS基础:字段的别名和字段属性域设置_arcgis字段约束条件怎么设置-程序员宅基地

【1】别名设置:别名设置时需要注意的是在SHP格式里,进行设置仅仅是临时存贮,关闭属性表后,属性的别名就会丢失,需要将其存储到地理数据库里才可以永久包括。存放在地理数据库后,找到数据,右键属性,找到字段,然后,在字段属性里把别名根据需求改一下,如下所示:把数据从新加载之后,可以发现属性表里就显示了别名,如下所示。【2】:【设置属性域】:属性域的设置能够限定后续输入数据的标准型,便于有效的进行管理。先要在文件夹里右键,新建一个地理数据库,进行命名,以下所示:然后再在【DB数据库】上右键,找到属性域,按照以_arcgis字段约束条件怎么设置

vue2.6 更新v-slot插槽_改变v-slot:传的值_北寂.的博客-程序员宅基地

slot种类:  匿名插槽、具名插槽、作用域插槽子组件ChildrenHasSlot.vue:<template> <div> 我是子组件ChildrenHasSlot.vue <slot>我是默认值</slot> <slot name="chacaoB">我是chacaoB默认值</slot> <slot name="chacaoC" :data1="data1" :data2=_改变v-slot:传的值

元学习系列(二):Prototypical Networks(原型网络)-程序员宅基地

之前我们了解了孪生网络以及他是如何处理one-shot learning的例子,现在我们再来看看另一个模型,原型网络Prototypical Networks。之前说过,孪生网络的缺点就是要对比目标和过去每个样本之间的相似度,从而分析目标的类别,而原型网络就提出,先把样本投影到一个空间,计算每个样本类别的中心,在分类的时候,通过对比目标到每个中心的距离,从而分析出目标的类别:大致思路很简单..._prototypical networks