首页 > 其他分享 >lwip--让你的设备拥有PING别的设备的功能

lwip--让你的设备拥有PING别的设备的功能

时间:2024-09-26 16:13:22浏览次数:8  
标签:Info iecho lwip -- Ping PING ip ping Data

/**/

点击查看代码
#include "CompletePing.h"

/** ping identifier - must fit on a u16_t */
#ifndef PING_ID
#define PING_ID        0xAFAF// Ping包的唯一ID
#endif

#define PING_DATA_SIZE 32          // Ping数据大小

static u32_t ping_time = 0;
static uint8_t Ping_index;

static struct raw_pcb *ping_pcb = NULL;

// 互斥锁保护缓冲区,避免并发访问(可选,视具体环境是否需要)
sys_mutex_t ip_mutex;

//
void update_ip_buffer(char dev_index,const char *new_ip) {
    // 进入临界区,保护缓冲区
    sys_mutex_lock(&ip_mutex);
    
    // 清空缓冲区,并复制新的IP地址
    memset(PDU_Info_Data.IP_Addr[dev_index].IP_Addr_buf, 0, 40);
    sprintf(PDU_Info_Data.IP_Addr[dev_index].IP_Addr_buf,"%s",new_ip);
    
    PDU_Info_Data.IP_Addr[dev_index].ip_updated = true;  // 标记为已更新
    sys_mutex_unlock(&ip_mutex);  // 释放互斥锁
}
//
static u8_t ping_recv_callback(void *arg, struct raw_pcb *pcb, struct pbuf *p,const ip_addr_t *addr)
{
    struct ip_hdr *iphdr;
    u16_t iphdr_hlen;
	struct icmp_echo_hdr *iecho;
    u16_t echo_type;
    u16_t echo_id;
	LWIP_UNUSED_ARG(arg);
	LWIP_UNUSED_ARG(pcb);
	LWIP_UNUSED_ARG(addr);
	LWIP_ASSERT("p != NULL", p != NULL);
    
    // 获取IP头部的长度,IPv4最常见的头部长度是20字节
    iphdr = (struct ip_hdr *)p->payload;
    iphdr_hlen = IPH_HL(iphdr) * 4;  // 头部长度是以4字节为单位的
    // 跳过IP头部,获取ICMP头部
    iecho = (struct icmp_echo_hdr *)((u8_t*)p->payload + iphdr_hlen);
    
    #if 1
    echo_type = __REV16(ICMPH_TYPE(iecho));
    echo_id = __REV16(iecho->id);
    #else
    printf("iecho->type = [%x]\r\n",echo_type);
    printf("iecho->id = [%x]\r\n",echo_id);
    printf("\r\niecho->type2 = [%x]\r\n",iecho->type);
    printf("iecho->chksum2 = [%x]\r\n",iecho->chksum);
    printf("iecho->code2 = [%x]\r\n",iecho->code);
    printf("iecho->id2 = [%x]\r\n",iecho->id);
    printf("iecho->seqno2 = [%x]\r\n",iecho->seqno);
    #endif
    
	if ((echo_type == ICMP_ER) && echo_id == PING_ID) {
		printf("ping: recv timeout %"U32_F" ms\n", (PDU_Info_Data.PingTimeOutms[Ping_index] = (sys_now()-ping_time)));
		xSemaphoreGiveFromISR(xSemaphorePING, NULL);// 释放二值信号量,通知设备PING响应成功
        pbuf_free(p);
        return 1; // 成功接收ping回复
	}
	return 0;
}
/**/
static void ping_send(struct raw_pcb *pcb, const ip_addr_t *addr) {
    struct pbuf *p;
    struct icmp_echo_hdr *iecho;
    size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
    
    p = pbuf_alloc(PBUF_IP, ping_size, PBUF_RAM);
    if (p != NULL) {
        iecho = (struct icmp_echo_hdr *)p->payload;
        ICMPH_TYPE_SET(iecho, ICMP_ECHO);
        ICMPH_CODE_SET(iecho, 0);
        iecho->chksum = 0;
        iecho->id = PING_ID;
        iecho->seqno = htons(0x0100);
        
        iecho->chksum = inet_chksum(iecho, ping_size);
        raw_sendto(pcb, p, addr);
        pbuf_free(p);
    }
}
//
#if(1)
/*ping函数用于ping其他设备*/
static void Ping_test(char *pIPaddr)
{
    static ip_addr_t target_ip;
	unsigned int inaddr=0l;
	struct hostent *host;
	char *ip_str = NULL;
	u8 Ping_remote_ip[4] = {0};
	
	/*判断是主机名还是ip地址*/
	inaddr=inet_addr(pIPaddr);
    if(inaddr == INADDR_NONE)
    {
		printf("用户ping输入的类型为域名%s\r\n",pIPaddr);
		host=gethostbyname(pIPaddr);
		if(host != NULL) /**/
		{
			 ip_str = inet_ntoa(*((struct in_addr *)host->h_addr_list[0]));// 只取第一个 IP 地址
		}
	}
	else
	{
		ip_str = pIPaddr;
	}
	sscanf(ip_str, "%hhu.%hhu.%hhu.%hhu", &Ping_remote_ip[0], &Ping_remote_ip[1], &Ping_remote_ip[2], &Ping_remote_ip[3]);	
	printf("用户ping的ip地址为%hhu.%hhu.%hhu.%hhu ",Ping_remote_ip[0], Ping_remote_ip[1], Ping_remote_ip[2], Ping_remote_ip[3]);
	IP4_ADDR(&target_ip, Ping_remote_ip[0],Ping_remote_ip[1],Ping_remote_ip[2],Ping_remote_ip[3]);//MCU 要ping的设备IP
	
    if (1)
    {
        ping_send(ping_pcb, &target_ip);
        
		ping_time = sys_now();
        
		if(xSemaphoreTake(xSemaphorePING,1000))//等待1000ms获取信号量
		{
			printf("PING success!\r\n");
		}
		else
		{
			PDU_Info_Data.PingTimeOutms[Ping_index] = 5000;
			printf("PING timeout is more than 1000ms\r\n");
			#if (0)
			if(PDU_Info_Data.timeout_action[Ping_index] == 0)//重启
			{
				vTaskDelay((PDU_Info_Data.OpenDalay[Ping_index]));	//断开延时
				Set_Data_Bit(&(PDU_Info_Data.ralay_status),Ping_index,0);//设置插座状态
				Set_Relays_Status(PDU_Info_Data.ralay_status);//发送状态断开对应插座
				vTaskDelay((PDU_Info_Data.CloseDalay[Ping_index]));	//断开延时
				Set_Data_Bit(&(PDU_Info_Data.ralay_status),Ping_index,1);//设置插座状态
				Set_Relays_Status(PDU_Info_Data.ralay_status);//闭合对应插座
			}
			else if(PDU_Info_Data.timeout_action[Ping_index] == 1)//关闭插座
			{
				vTaskDelay((PDU_Info_Data.OpenDalay[Ping_index]));	//断开延时
				Set_Data_Bit(&(PDU_Info_Data.ralay_status),Ping_index,0);//设置插座状态
				Set_Relays_Status(PDU_Info_Data.ralay_status);//发送状态断开对应插座
			}
			else//重置超时动作
			{
				PDU_Info_Data.timeout_action[Ping_index] = 0;
			}
			#endif
		}
    }
	
}
#endif
//
static void ping_device_thread(void *pvParameters)
{
    // 创建raw PCB
    ping_pcb = raw_new(IP_PROTO_ICMP);
    if (ping_pcb != NULL) {
        raw_recv(ping_pcb, ping_recv_callback, NULL);  // 设置接收回调
    }
    
    #ifdef PING_DEBUG
    PDU_Info_Data.IP_Addr[0].ip_updated = true;
    sprintf(PDU_Info_Data.IP_Addr[0].IP_Addr_buf,"%s","192.168.1.140");
    #endif
    
    for(;;)
    {
        for(int i=0;i<6;i++)
        {
            sys_mutex_lock(&ip_mutex);  // 进入临界区,保护缓冲区PDU_Info_Data.IP_Addr[i]
            if (PDU_Info_Data.IP_Addr[i].ip_updated) // 如果IP已更新
            {  
//                PDU_Info_Data.IP_Addr[0].ip_updated = false;
                Ping_test(PDU_Info_Data.IP_Addr[i].IP_Addr_buf);
            }
            sys_mutex_unlock(&ip_mutex);  // 释放互斥锁
            vTaskDelay(100);  // 每隔1秒检查一次缓冲区
        }
        
    }
}
//
void ping_thread_create(void)
{
    // 初始化互斥锁
    sys_mutex_new(&ip_mutex);
    
    xTaskCreate(ping_device_thread, "ping_device_thread", 512, NULL,9, NULL);//
}

标签:Info,iecho,lwip,--,Ping,PING,ip,ping,Data
From: https://www.cnblogs.com/embedded-jee/p/18433621

相关文章

  • 为什么投递简历都是已读不回?
    星球有同学找我咨询,说自己最近投递了很多测试岗位,但基本上都是消息已读不回,很少有HR会回复消息,更不要提主动打招呼要简历约面试的,目前很苦恼,问有什么办法能提高面试邀约概率。在当下的就业环境背景下,对大部分求职者来说,已读不回是正常的情况。毕竟企业现在要的是降本增效活下去,......
  • 数学分解软件CNum2025下载download
    本软件可以算单个整数的因式分解。本软件可以算2个整数的最大公因数、最小公倍数。本软件可以判断输入的整数是否是素数或者合数。本软件支持中英文双语界面,可以打开、保存和清空工作数据。本软件是共享软件,支持软件,可以获得更好的未来的软件。Thissoftwarecancalculatet......
  • 标志寄存器
    一、 1、进位标志寄存器CF(CarryFlag):如果运算结果的最高位产生了一个进位或借位,那么其值为1,否则为0MOVAL,0xEF                           MOVAL,0xFEADDAL,2                  ......
  • 仅需6步,实现虚拟物体在现实世界的精准放置
    增强现实(AR)技术作为一种将数字信息和现实场景融合的创新技术,近年来得到了快速发展,并在多个应用领域展现出其独特的魅力。比如在教育行业,老师可以通过虚拟现实场景生动直观地帮助学生理解抽象概念;在旅游行业,AR技术还能虚拟历史文化场景、虚拟导航等,为游客提供更加沉浸的互动体验。......
  • STM32F103C8T6+ESP8266+MQTT+EMQX完成数据上传和点灯环节
    本文参考以下文章:【最简单】STM32+ESP8266+MQTT+EMQX完成数据上传和点灯环节_stm32如何连接emqx-CSDN博客STM32+ESP8266通过MQTT协议连接本地EMQX(保姆级教学!资料开放!)_stm32驱动esp8266本地emqx-CSDN博客 一、在windows环境下或Ubuntu搭建EMQX云平台 参看这篇文章:搭建自己的M......
  • 【LeetCode Hot 100】20. 有效的括号
    题目描述这个题目在讲解栈的应用的时候是常用的例子,在遍历括号串的时候维护一个栈结构,如果当前字符是前括号,暂时没有与之配对的后括号,则先将其压入栈中。C++STL和Java都提供了对应的容器,但是由于我们知道栈的大小不可能超过括号串的长度,所以也可以手动用数组模拟,这样运行速度可......
  • 中电金信:“源启”金融级数字底座
    ​01方案简介金融级数字底座是中电金信依托中国电子自主安全计算产业链,采用新一代技术架构,为金融及重点行业打造的数字化新型基础设施。“源启”面向金融等重点行业场景,依照系统工程方法论,进行全栈技术产品的验证、适配和调优,实现软硬一体化设计和垂直打穿,打造可替代传统架构的......
  • NOIP2024集训Day39 DP
    NOIP2024集训Day39DPA.[AGC002F]LeftmostBall反向考虑,从最终状态,倒退它能指向多少种初始状态。dp策略:从左往右放,每次对最左边的一个空位,要么放一个白球,要么放一个有颜色的球,同时把该种颜色剩下的球都放到后面的位置去。具体的:定义\(f_{i,j}\)表示当前有\(i\)个白球......
  • 数据库系统------ER图中的符号
    矩形实体集:实体是指在现实世界中可独立存在的对象或事物,实体集就是相同类型实体的集合,可以看成是一个类画在实体集中的属性A1表示简单属性A2表示复合属性,即由多个子属性组成的属性,这里是指A2.1和A2.2,例如,地址可以分为街道、城市和邮政编码A3表示多值属性,即该属......
  • ECU电控软件开发及测试介绍
        伴随着电动化、智能化、网联化等技术发展的时代背景,各行各业电子电气架构都在发生深度变革。新型架构逐渐取代传统架构,比如汽车、工程机械、储能、船舶等领域,电子电气架构从传统分布式向域集中式,甚至向着中央集中式发展,控制器功能呈现集中化、复杂化的特点。为了提升开......