(ESP32学习记录)在ESP32C3上实现UDP服务器和客户端

借鉴ESP32官方例程实现了简单的UDP服务器和客户端,代码如下:

/*UDP服务器端和客户端*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "nvs_flash.h"
#include "wifi_provisioning/manager.h"
#include "wifi_provisioning/scheme_softap.h"
#include "socket.h"
#include "esp_http_server.h"
/*宏定义*/
#define ERASE_NVS 0
// 清除储存的wifi密码->0: 沿用上次的WIFI信息进行连接; 1: 清除WIFI信息,使用SOFTAP一键配网进行新链接
#define UDP_SERVER_OR_CLIENT 1
//ESP32作为服务器端0还是客户端1
/*函数声明*/
void WIFI_CALLBACK_FUN(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data); // 事件队列回调函数
void wifi_connect(void);                                                                                          // WIFI连接处理函数
/*全局变量*/
int LINK_WIFI_SUCCESS = 255;    //表示,用于确认是否连接WIFI成功
char recv_buf[1024] = {0};
/***************************************************************************************************************/
/*MAIN函数*/
void app_main(void)
{
    wifi_connect(); // 连接wifi
#if UDP_SERVER_OR_CLIENT != 0           //UDP客户端
    /*1. 创建socket fd*/
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd < 0) goto error_line;
    /*2. 收发数据*/
    struct sockaddr_in host_ip = 
    {
        .sin_family = AF_INET,
        .sin_addr.s_addr = inet_addr("192.168.137.255"),
        .sin_port = htons(3333)
    };
    int cnt = 0;
    char num_buf[10] = {0};
    while(1)
    {
        cnt ++;
        itoa(cnt, num_buf, 10);
        sendto(fd, "正在进行客户端发送测试, Times: ", strlen("正在进行客户端发送测试, Times: "), 0, (struct sockaddr *)&host_ip, sizeof(host_ip));
        sendto(fd, num_buf, strlen(num_buf), 0, (struct sockaddr *)&host_ip, sizeof(host_ip));
        printf("第%d次发送测试!\n", cnt);
        vTaskDelay(300);
    }
#else                                   //UDP服务器端
    /*1. 创建socket*/
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd < 0) goto error_line;
    /*1.x setsocket SO_REUSERADDR, 允许服务器绑定当前已建立连接的地址*/
    int opt_val = 1;
    int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val));
    if(ret < 0) goto error_line;
    /*2. bind绑定IP*/
    struct sockaddr_in udp_addr_para= 
    {
        .sin_family = AF_INET,
        .sin_addr.s_addr = INADDR_ANY,
        .sin_port = htons(3333)
    };
    ret = bind(fd, (struct sockaddr *)&udp_addr_para, sizeof(udp_addr_para));
    if(ret < 0) goto error_line;
    /*3. 接收数据*/
    struct sockaddr_in recv_addr;
    socklen_t recv_addr_len = sizeof(recv_addr);
    memset(&recv_addr, 0, sizeof(recv_addr));   //将recv_addr占据空间置零
    int cnt = 0;
    while(1)
    {
        cnt ++;
        printf("开始第%d次接收数据!\n", cnt);
        int len = recvfrom(fd, recv_buf, sizeof(recv_buf)-1, 0, (struct sockaddr *)&recv_addr, &recv_addr_len);
        if(len < 0) goto error_line;
        printf("已经接收到%d个char型数据\n", len);
        recv_buf[len] = '\0';
        printf("接收的数据为: %s\n", recv_buf);
        printf("数据来源IP为: %s\n\n", inet_ntoa(recv_addr.sin_addr.s_addr));
        sendto(fd, "服务器收到:", sizeof("服务器收到:"), 0, (struct sockaddr *)&recv_addr, sizeof(recv_addr));
        sendto(fd, recv_buf, strlen(recv_buf), 0, (struct sockaddr *)&recv_addr, sizeof(recv_addr));
    }
#endif
    /*end. 错误处理*/
error_line:
    /*4. 关闭fd*/
    close(fd);
    while(1)
    {
        vTaskDelay(200);
        printf("出错,阻塞线程!\n");
    }
}
/**********************************************************************************************/
/*回调函数*/
void WIFI_CALLBACK_FUN(void *event_handler_arg, esp_event_base_t eb, int32_t ei, void *event_data)
{
    if (eb == WIFI_EVENT)
    {
        if (ei == WIFI_EVENT_STA_START)
        {
            esp_wifi_connect(); // 开始连接WIFI
            printf("正在连接WIFI!\n");
        }
        if (ei == WIFI_EVENT_STA_DISCONNECTED)
        {
            nvs_flash_erase();  //清除旧密码
            nvs_flash_init();
            printf("自动连接失败,正在启动SOFTAP配网服务!\n");
            const char *pop = "abcd1234";
            const char *wifi_name = "SOFTAP_PROV_MGR_PROB";
            const char *wifi_key = "12345678";
            wifi_prov_mgr_start_provisioning(WIFI_PROV_SECURITY_1, pop, wifi_name, wifi_key);
            wifi_prov_mgr_wait();
            wifi_prov_mgr_deinit();
            printf("Provisioning服务结束,连接WIFI成功!\n");
        }
    }
    if (eb == IP_EVENT && ei == IP_EVENT_STA_GOT_IP)
    {
        printf("WIFI连接成功!\n");
        ip_event_got_ip_t *sta_ip = (ip_event_got_ip_t *)event_data;
        printf("本机IP地址为: " IPSTR "\n", IP2STR(&sta_ip->ip_info.ip));
        LINK_WIFI_SUCCESS = 0;  //已经连接成功标识清零
        
    }
}

/*连接WIFI*/
void wifi_connect(void)
{
    nvs_flash_init();
#if ERASE_NVS != 0
    nvs_flash_erase();
    nvs_flash_init();
#endif
    esp_event_loop_create_default(); // 创建默认事件队列
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, WIFI_CALLBACK_FUN, NULL, NULL);
    esp_netif_init();                    // 初始化网卡
    esp_netif_create_default_wifi_ap();  // 创建默认网卡ap
    esp_netif_create_default_wifi_sta(); // 创建默认网卡sta
    wifi_init_config_t esp_wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&esp_wifi_init_config); // 初始化WIFI功能
    /*softAP配网*/
    wifi_prov_mgr_config_t wifi_prov_mgr_config_t =
    {
            .scheme = wifi_prov_scheme_softap,
            .app_event_handler = WIFI_PROV_EVENT_HANDLER_NONE
    };
    wifi_prov_mgr_init(wifi_prov_mgr_config_t);
    bool wifi_prov_mgr_diag = false;
    wifi_prov_mgr_is_provisioned(&wifi_prov_mgr_diag);
    if (wifi_prov_mgr_diag == false)
    {
        const char *pop = "abcd1234";
        const char *wifi_name = "SOFTAP_PROV_MGR_PROB";
        const char *wifi_key = "12345678";
        wifi_prov_mgr_start_provisioning(WIFI_PROV_SECURITY_1, pop, wifi_name, wifi_key);
        wifi_prov_mgr_wait();
        wifi_prov_mgr_deinit();
        printf("Provisioning服务结束,连接WIFI成功!\n");
    }
    else
    {
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_START, WIFI_CALLBACK_FUN, NULL, NULL);        // 注册WIFI开启事件
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, WIFI_CALLBACK_FUN, NULL, NULL);    // 注册WIFI连接事件
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, WIFI_CALLBACK_FUN, NULL, NULL); // 注册WIFI连接失败事件
        esp_wifi_start();
    }
    esp_wifi_set_ps(WIFI_PS_NONE); // 关闭WIFI的省电模式
    while(LINK_WIFI_SUCCESS)   //等到WIFIF连接成功
    {
        vTaskDelay(1);         //防止看门狗复位
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值