首页
最新活动
服务器租用
香港服务器租用
台湾服务器租用
美国服务器租用
日本服务器租用
新加坡服务器租用
高防服务器
香港高防服务器
台湾高防服务器
美国高防服务器
裸金属
香港裸金属服务器
台湾裸金属服务器
美国裸金属服务器
日本裸金属服务器
新加坡裸金属服务器
云服务器
香港云服务器
台湾云服务器
美国云服务器
日本云服务器
CDN
CDN节点
CDN带宽
CDN防御
CDN定制
行业新闻
官方公告
香港服务器资讯
帮助文档
wp博客
zb博客
服务器资讯
联系我们
关于我们
机房介绍
机房托管
登入
注册
帮助文档
专业提供香港服务器、香港云服务器、香港高防服务器租用、香港云主机、台湾服务器、美国服务器、美国云服务器vps租用、韩国高防服务器租用、新加坡服务器、日本服务器租用 一站式全球网络解决方案提供商!专业运营维护IDC数据中心,提供高质量的服务器托管,服务器机房租用,服务器机柜租用,IDC机房机柜租用等服务,稳定、安全、高性能的云端计算服务,实时满足您的多样性业务需求。 香港大带宽稳定可靠,高级工程师提供基于服务器硬件、操作系统、网络、应用环境、安全的免费技术支持。
联系客服
服务器资讯
/
香港服务器租用
/
香港VPS租用
/
香港云服务器
/
美国服务器租用
/
台湾服务器租用
/
日本服务器租用
/
官方公告
/
帮助文档
ESP32接入网络后,循环扫描服务器IP及端口状态信息(ESP-IDF)
发布时间:2024-03-06 04:33:10 分类:帮助文档
ESP32接入网络后,循环扫描服务器IP及端口状态信息(ESP-IDF) 0、代码说明 本文使用的是ESP32系列的ESP32S3设备开发,ESP-IDF框架版本为ESP-IDF V5.1,在VScode下以ESP-IDF插件的形式对设备开发。后期经过对程序的测试发现,在ESP-IDF v4.4框架下编译开发,也可以实现循环扫描功能,实现功能的程序源码Demo见文末。 1、实现背景 在嵌入式物联网这一类的项目开发中,硬件设备常作为客户端,通过固定的或非固定的服务器IP地址和端口号向服务器进行通信,上传本地数据到服务器中或接收来自服务器的请求数据。本文主要解决当服务器IP地址并未固定或者因某种原因导致服务器的IP地址发生变动,而硬件设备产品可能已经上市交付等其它因素,并不能及时的通过OTA升级更新客户端的MCU硬件程序,但硬件产品依然需要连接服务器的端口,进行数据交互。 为了预防避免这些意外,在硬件设备程序的编写中,并不能和往常一样直接固定了服务器IP地址。本博客文章中提供了一种简单可行的方法,即:客户端固定了目标服务器的IP端口,但服务器的IP地址并不固定。当然,也可以先进行对某一固定了IP和端口的服务器进行连接,在多次或者一定时间都不能正常接入服务器后,开启循环扫描同一网段的服务器IP,连接该固定端口或备用端口。 2、开发资料参考 乐鑫官方的ESP-IDF编程API参考指南链接:API 指南 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档 (espressif.com) 通过API编程参考,可以查看ESP32所需要的常用API及其使用的Demo案例。 3、程序效果图 ESP32接入WiFi网络后获取到的IP地址信息 ESP32扫描到在线的IP地址,但未扫描到对应的端口,如果服务器未开启,则ESP32会一直循环扫描服务器的IP及端口。 ESP32扫描到服务器的IP地址和端口 服务器的IP地址 ESP32接入服务器后,服务器端收到来自客户端发送的数据 4、程序源码 ①、main.c #include
#include
#include "esp_wifi.h" #include "esp_log.h" #include "nvs_flash.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "network.h" //设备启动接入WiFi后,循环扫描服务器ip是否在线,通信端口是否打开 int app_main() { printf("Program starting...\n"); int ret = 0; char server_ip[128] = {0}; uint8_t wifi_ssid[] = "imi-12-1719"; uint8_t wifi_passwd[] = "imi?61415926"; device_connect_wifi_ap(wifi_ssid, wifi_passwd); vTaskDelay(500); while(1) { ret = device_scan_dest_server(server_ip); if(ret == 0) { printf("Server ip:%s\n", server_ip); break; } vTaskDelay(30000 / portTICK_PERIOD_MS); } //连接服务器 extern int tcp_sock; tcp_client_init(server_ip); char str[] = "hello server!"; send(tcp_sock, str, strlen(str)+1, 0); close(tcp_sock); return 0; } ②、network.c #include "network.h" //ESP-IDF v5.1 static const char *TAG = "wifi_station"; int tcp_sock = -1; int udp_sock = -1; esp_ping_handle_t ping; int ping_flag = -1; enum { PING_IP_OK = 0, PING_IP_ERR }; struct sockaddr_in dest_addr; / * @brief 连接WiFi事件处理器---处理WiFi和IP事件 * @param arg:用户定义的参数 * @param event_base:事件基类型 * @param event_id:事件具体ID * @param event_data:指向事件数据的指针 * @retval void */ void connect_wifi_ap_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { esp_wifi_connect(); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; char addr_str[IP4ADDR_STRLEN_MAX]; ESP_LOGI(TAG, "got ip:%s", esp_ip4addr_ntoa(&event->ip_info.ip, addr_str, IP4ADDR_STRLEN_MAX)); } } / * @brief 设备连接WiFi AP热点 * @param wifi_ssid:WiFi 热点ID * @param wifi_passwd:WiFi密码 * @retval void */ void device_connect_wifi_ap(uint8_t *wifi_ssid, uint8_t *wifi_passwd) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &connect_wifi_ap_event_handler, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_wifi_ap_event_handler, NULL)); wifi_config_t wifi_config; memcpy(wifi_config.sta.ssid, wifi_ssid, strlen((char *)wifi_ssid)+1); memcpy(wifi_config.sta.password, wifi_passwd, strlen((char *)wifi_passwd)+1); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); } / * @brief udp客户端初始化 * @param None * @retval 成功返回0,失败返回-1 */ int udp_client_init(void) { char host_ip[] = HOST_IP_ADDR; int addr_family = 0; int ip_protocol = 0; #if defined(CONFIG_EXAMPLE_IPV4) //struct sockaddr_in dest_addr; dest_addr.sin_addr.s_addr = inet_addr(host_ip); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(PORT); addr_family = AF_INET; ip_protocol = IPPROTO_IP; #elif defined(CONFIG_EXAMPLE_IPV6) struct sockaddr_in6 dest_addr = {0}; inet6_aton(HOST_IP_ADDR, &dest_addr.sin6_addr); dest_addr.sin6_family = AF_INET6; dest_addr.sin6_port = htons(PORT); dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE); addr_family = AF_INET6; ip_protocol = IPPROTO_IPV6; #elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN) struct sockaddr_storage dest_addr = {0}; ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_DGRAM, &ip_protocol, &addr_family, &dest_addr)); #endif extern int udp_sock; udp_sock = socket(addr_family, SOCK_DGRAM, ip_protocol); if (udp_sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); return -1; } ESP_LOGI(TAG, "Socket created, sending to %s:%d", HOST_IP_ADDR, PORT); return 0; } / * @brief tcp客户端初始化 * @param None * @retval 成功返回0,失败返回-1 */ int tcp_client_init(char ip_addr[]) { //char host_ip[128] = HOST_IP_ADDR; char host_ip[128] = {0}; memcpy(host_ip, ip_addr, strlen(ip_addr)); int addr_family = 0; int ip_protocol = 0; int err = 0; #if defined(CONFIG_EXAMPLE_IPV4) struct sockaddr_in dest_addr; dest_addr.sin_addr.s_addr = inet_addr(host_ip); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(PORT); addr_family = AF_INET; ip_protocol = IPPROTO_IP; #elif defined(CONFIG_EXAMPLE_IPV6) struct sockaddr_in6 dest_addr = { 0 }; inet6_aton(host_ip, &dest_addr.sin6_addr); dest_addr.sin6_family = AF_INET6; dest_addr.sin6_port = htons(PORT); dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE); addr_family = AF_INET6; ip_protocol = IPPROTO_IPV6; #elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN) struct sockaddr_storage dest_addr = { 0 }; ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_STREAM, &ip_protocol, &addr_family, &dest_addr)); #endif extern int tcp_sock; tcp_sock = socket(addr_family, SOCK_STREAM, ip_protocol); if (tcp_sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); return -1; } ESP_LOGI(TAG, "Socket created, connecting to server"); DPRINTF("Socket created, connecting to %s:%d\n", host_ip, PORT); err = connect(tcp_sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6)); if (err != 0) { ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno); return -1; } ESP_LOGI(TAG, "Successfully connected"); return 0; } / * @brief 设备连接服务器 * @param target_ip:目标IP地址 * @retval 成功返回0,失败返回-1 */ int device_connect_to_server(char *target_ip) { int sock = 0; struct sockaddr_in serv_addr; //#define PORT 5005 DPRINTF("FUNCTION:%s\tLINE:%d\n", __FUNCTION__, __LINE__); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { DPRINTF("\n Socket creation error \n"); close(sock); return -1; } DPRINTF("FUNCTION:%s\tLINE:%d\n", __FUNCTION__, __LINE__); memset(&serv_addr, '0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); if(inet_pton(AF_INET, target_ip, &serv_addr.sin_addr)<=0) { DPRINTF("\nInvalid address/ Address not supported \n"); close(sock); return -1; } DPRINTF("FUNCTION:%s\tLINE:%d\n", __FUNCTION__, __LINE__); if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { //send(sock, "hello", strlen("hello"), 0); DPRINTF("\nConnection Failed %s\t%d\n", target_ip, PORT); close(sock); return -1; } DPRINTF("Connected to %s:%d\n", target_ip, PORT); //char str[] = "hello server!"; //send(sock, str, strlen(str)+1, 0); close(sock); return 0; } / * @brief TCP扫描同一网段下的目标服务器设备 * @param target_ip:目标IP地址 * @retval 成功返回0, 失败返回-1 */ int device_scan_dest_server(char ip_addr[]) { char ip_local_addr[128] = {0}; char ip_search_addr[256] = {0}; esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); esp_netif_ip_info_t ip_info; esp_netif_get_ip_info(netif, &ip_info); memcpy(ip_local_addr, ip4addr_ntoa((ip4_addr_t *)&ip_info.ip), strlen(ip4addr_ntoa((ip4_addr_t *)&ip_info.ip))); //char *ip4addr_ntoa(const ip4_addr_t *addr); printf("device ip:%s\n", ip_local_addr); //192.168.1.8 int i, self_ip_com = 0; int tok_cnt = 1; int ret = -1; for(i = 0; i < 128; i++) { if(ip_local_addr[i] == '.')//获取所在网段 { if(tok_cnt == 3) { self_ip_com = ip_local_addr[i+1] - '0'; break; } tok_cnt++; } //DPRINTF("%c %d\n", ip_local_addr[i], i); } DPRINTF("self_ip_com:%d\n", self_ip_com); DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); char ip_addr_temp[128] = {0}; strncpy(ip_addr_temp, ip_local_addr, i+1); DPRINTF("%s\n", ip_addr_temp); int com; for(com = 1; com < 255; com++) { if(com == self_ip_com) continue; sprintf(ip_search_addr, "%s%d", ip_addr_temp, com); //DPRINTF("%s\n", ip_search_addr); DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); device_ping_ip_addr(ip_search_addr);//ping传入的ip地址 vTaskDelay(500 / portTICK_PERIOD_MS); //ping通ip地址后,继续判断是否能够连接端口(5005) if(ping_flag == PING_IP_OK) { esp_ping_stop(ping); esp_ping_delete_session(ping); DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); ret = device_connect_to_server(ip_search_addr); if (ret == 0) { DPRINTF("Found the target server.\n"); memcpy(ip_addr, ip_search_addr, strlen(ip_search_addr)); break; } }else{ DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); //vTaskDelay(300 / portTICK_PERIOD_MS); esp_ping_stop(ping); esp_ping_delete_session(ping); } DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); //DPRINTF("try again.\n"); memset(ip_search_addr, 0, sizeof(ip_search_addr)); } DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); printf("com = %d\n", com); if(com < 255) { DPRINTF("Device scan server success.\n"); return 0; }else{ DPRINTF("Device scan server failed.\n"); return -1; } } / * @brief ping ip地址成功的回调函数 * @param handle:ping ip句柄 * @param args:传入给回调函数的参数 * @retval None */ void ping_ip_success(esp_ping_handle_t handle, void *args) { // optionally, get callback arguments // const char* str = (const char*) args; // DPRINTF("%s\r\n", str); // "foo" ping_flag = PING_IP_OK; uint8_t ttl; uint16_t seqno; uint32_t elapsed_time, recv_len; ip_addr_t target_addr; esp_ping_get_profile(handle, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno)); esp_ping_get_profile(handle, ESP_PING_PROF_TTL, &ttl, sizeof(ttl)); esp_ping_get_profile(handle, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr)); esp_ping_get_profile(handle, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len)); esp_ping_get_profile(handle, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time)); printf("%ld bytes from %s icmp_seq=%d ttl=%d time=%ld ms\n", recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time); } / * @brief ping ip地址超时的回调函数 * @param handle:ping ip句柄 * @param args:传入给回调函数的参数 * @retval None */ void ping_ip_timeout(esp_ping_handle_t handle, void *args) { ping_flag = PING_IP_ERR; uint16_t seqno; ip_addr_t target_addr; esp_ping_get_profile(handle, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno)); esp_ping_get_profile(handle, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr)); printf("From %s icmp_seq=%d timeout\n", inet_ntoa(target_addr.u_addr.ip4), seqno); } / * @brief ping ip地址结束的回调函数 * @param handle:ping ip句柄 * @param args:传入给回调函数的参数 * @retval None */ void ping_ip_end(esp_ping_handle_t handle, void *args) { uint32_t transmitted; uint32_t received; uint32_t total_time_ms; ping_flag = -1; esp_ping_get_profile(handle, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted)); esp_ping_get_profile(handle, ESP_PING_PROF_REPLY, &received, sizeof(received)); esp_ping_get_profile(handle, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms)); DPRINTF("%ld packets transmitted, %ld received, time %ldms\n", transmitted, received, total_time_ms); } / * @brief ping ip地址 * @param ip_str:字符串格式的IP地址 "192.168.1.8" * @retval None */ void device_ping_ip_addr(char *ip_str) { DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); ip_addr_t target_addr; esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG(); ping_config.interval_ms = 400; ping_config.timeout_ms = 400; memset(&target_addr, 0, sizeof(ip_addr_t)); //字符串IP地址转换为ping_addr if (ipaddr_aton(ip_str, &target_addr)) { //DPRINTF("转换成功.\n"); ping_config.target_addr = target_addr; } else { DPRINTF("Invalid IP address\n"); return ; } DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); //ping_config.target_addr = target_addr; // target IP address ping_config.count = ESP_PING_COUNT_INFINITE; // ping in infinite mode, esp_ping_stop can stop it //设置回调函数 esp_ping_callbacks_t cbs; cbs.on_ping_success = ping_ip_success; cbs.on_ping_timeout = ping_ip_timeout; cbs.on_ping_end = ping_ip_end; cbs.cb_args = "ping ip"; // arguments that will feed to all callback functions, can be NULL DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); esp_ping_new_session(&ping_config, &cbs, &ping); DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); esp_ping_start(ping); DPRINTF("%s\t%d\n", __FUNCTION__,__LINE__); } ③、network.h #ifndef __NETWORK_H #define __NETWORK_H #include
#include
#include
#include
#include "sdkconfig.h" #include
#include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "freertos/queue.h" #include "esp_system.h" #include "esp_wifi.h" #include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" #include "esp_netif.h" #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/inet.h" #include "lwip/ip4_addr.h" #include "lwip/sys.h" #include
#include "esp_ping.h" #include "ping/ping_sock.h" #include "driver/gpio.h" #include
#include
#include
#include
// struct addrinfo #include
//#define __DEBUG__ //宏定义调试打印开关 #ifdef __DEBUG__ #define DPRINTF(...) printf(__VA_ARGS__) //宏调试打印函数定义 #else #define DPRINTF(...) #endif #define WIFI_SSID "tony" #define WIFI_PASS "1008611123" #if defined(CONFIG_EXAMPLE_IPV4) #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR #elif defined(CONFIG_EXAMPLE_IPV6) #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV6_ADDR #else #define HOST_IP_ADDR "192.168.1.100" #endif #define PORT 6666 void connect_wifi_ap_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); void device_connect_wifi_ap(uint8_t *wifi_ssid, uint8_t *wifi_passwd); int udp_client_init(void); int tcp_client_init(char ip_addr[]); void udp_client_task(void *pvParameters); void tcp_client_task(void *pvParameters); void key_udp_task(void *pvParameters); void key_tcp_task(void *pvParameters); int device_connect_to_server(char *target_ip); int device_scan_dest_server(char ip_addr[]); void ping_ip_success(esp_ping_handle_t handle, void *args); void ping_ip_timeout(esp_ping_handle_t handle, void *args); void ping_ip_end(esp_ping_handle_t handle, void *args); void device_ping_ip_addr(char *ip_str); extern esp_ping_handle_t ping; extern int ping_flag; extern int tcp_sock; extern int udp_sock; extern struct sockaddr_in dest_addr; #endif ④、完整工程源码 【免费】ESP32接入网络后,循环扫描服务器IP及端口是否在线的完整工程demo(ESP-IDF)资源-文库
上一篇
北京联想服务器租用多少钱
下一篇
海外独立服务器租用多少钱
相关文章
MySQL的binlog日志存储在哪个位置?
Apache服务器配置错误:客户端被服务器拒绝
服务器500g防御怎么样
怎么看数据服务器配置
服务器迁移应该怎么做
TCP服务器的演变过程:C++使用libevent库开发服务器程序
文件共享服务 配置文件服务器
使用Go语言的HTTP客户端和服务器
MobaXterm上传下载文件、文件夹到服务器上
香港云服务器租用推荐
服务器租用资讯
·广东云服务有限公司怎么样
·广东云服务器怎么样
·广东锐讯网络有限公司怎么样
·广东佛山的蜗牛怎么那么大
·广东单位电话主机号怎么填写
·管家婆 花生壳怎么用
·官网域名过期要怎么办
·官网邮箱一般怎么命名
·官网网站被篡改怎么办
服务器租用推荐
·美国服务器租用
·台湾服务器租用
·香港云服务器租用
·香港裸金属服务器
·香港高防服务器租用
·香港服务器租用特价
7*24H在线售后
高可用资源,安全稳定
1v1专属客服对接
无忧退款试用保障
德讯电讯股份有限公司
电话:00886-982-263-666
台湾总部:台北市中山区建国北路一段29号3楼
香港分公司:九龙弥敦道625号雅兰商业二期906室
服务器租用
香港服务器
日本服务器
台湾服务器
美国服务器
高防服务器购买
香港高防服务器出租
台湾高防服务器租赁
美国高防服务器DDos
云服务器
香港云服务器
台湾云服务器
美国云服务器
日本云服务器
行业新闻
香港服务器租用
服务器资讯
香港云服务器
台湾服务器租用
zblog博客
香港VPS
关于我们
机房介绍
联系我们
Copyright © 1997-2024 www.hkstack.com All rights reserved.