ESP32 IDF开发 应用篇⑮ Wifi UDP通信


别迷路-导航栏
快速导航找到你想要的(文章目录)

此篇文章如果对你有用,请点赞收藏,您的支持就是博主坚持的动力。

1、博主写这篇技术文章的目的:

(1)、了解 tcp udp的通信特点;
(2)、掌握udp编程;

2、概述

在前面章节已经为大家介绍了ESP32 WIFI STA 及AP模式的基本应用,本章是基于wifi sta模式开发。Tcp的理论知识这里就不过多介绍,大家百度一下比我讲解起来好多了。
TCP与UDP优缺点:
·TCP是面向连接,也就是发送数据之前是需要建立连接;UDP是面向无连接的,即发送数据之前不需要建立连接。
·TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力做到可靠,即不保证绝对可靠。
·UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
·每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
·TCP对系统资源要求较多,UDP对系统资源要求较少。

3、Socket API库的介绍

1、UDP 编程的客户端一般步骤是:
(1)创建 UDP socket 套接字,用 socket()函数;
(2)用 sendto()函数往指定的 IP,地址发送信息;
2、UDP 编程的服务器端一般步骤是:
(1)创建 UDP socket 套接字,用 socket();
(2)设置 socket 的属性,用 setsockopt()函数,(可选);
(3)绑定包含 IP 信息,地址信息的(IPv4)结构体。用 bind();
(4)循环接收消息,用 recvfrom()函数;
(5)关闭 socket 套接字;
ESP32 使用的是 LwIP,LwIP 是特别适用于嵌入式设备的小型开源 TCP/IP 协议栈,对内
存资源占用很小。ESP-IDF 即是移植了 LwIP 协议栈。
我们这里直接使用标准 socket API接口,API函数只做简单的介绍,跟详细的socket API大家可以百度
 创建连接socket ();
 关闭 socket 函数:close();
 获取 socket 错误代码:getsocketopt();
 接收数据函数:recvfrom ();
 发送数据函数:sendto ();
更多API 参考esp-idf\components\lwip\lwip\src\include\lwip\sockets.h

4、软件设计

(1)、客户端软件设计
①、等待wifi sta连接好路由器(前提条件是先设置好ssid 和password)
②、创建连接服务端的socket

udp_connect_socket = socket(AF_INET, SOCK_DGRAM, 0);

③、配置连接服务器信息,端口和IP
    udp_client_addr.sin_family = AF_INET;
    udp_client_addr.sin_port = htons(port);
    udp_client_addr.sin_addr.s_addr = inet_addr(ip);

④、然后直接发送数据

sendto(udp_connect_socket, databuff, 30, 0, (struct sockaddr *)
&udp_client_addr,sizeof(udp_client_addr));

5、实例

新建工程请参考【ESP32 IDF开发 应用篇⑬ Wifi TCP客户端和服务器通信】的实例部分
Wifi sta部分代码与上一篇一样这里不列出来
代码:udp_bsp.c

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_wifi.h"

#include <sys/socket.h>
#include "freertos/event_groups.h"
#include "esp_event.h"
#include "esp_err.h"
#include "nvs_flash.h"
#include "esp_smartconfig.h"
#include "esp_netif.h"
#include "esp_wpa2.h"

#include "esp_log.h"
#include "esp_ota_ops.h"
#include "nvs.h"
#include "udp_bsp.h"

//任务句柄 
static TaskHandle_t xHandleTaskUdp = NULL;

//任务堆栈大小,主要是函数嵌套参数入栈和局部变量的内存
#define Udp_TASK_STACK_SIZE     8192

//任务优先级,越大越高,跟ucos相反
#define Udp_TASK_PRIO           2

static int udp_connect_socket = 0;                     //客户端连接socket
static struct sockaddr_in udp_client_addr;                  //client地址

//函数声明
static void vTaskUdp(void *pvParameters);
static esp_err_t CreateUdpClient(const char *ip,uint16_t port);

/***********************************************************************
* 函数:  
* 描述:   创建tcp接收发送任务,给外部使用
* 参数:
* 返回: 无
* 备注:
************************************************************************/
void AppTaskCreate(void)
{
    xTaskCreate(vTaskUdp,                               // 任务函数 
            "vTaskUdp",                                 // 任务名
            Udp_TASK_STACK_SIZE,                        // 任务栈大小,单位 word,也就是 4 字节
            NULL,                                       // 任务参数 
            Udp_TASK_PRIO,                              // 任务优先级
            &xHandleTaskUdp);                           // 任务句柄 
}
/***********************************************************************
* 函数:  
* 描述:   创建UDP客户端连接
* 参数:ip:IP地址,port:端口号
* 返回: 无
* 备注:
************************************************************************/
static esp_err_t CreateUdpClient(const char *ip,uint16_t port)
{
    //等待连接成功,或已经连接有断开连接,此函数会一直阻塞,只有有连接
   EventBits_t bits =  xEventGroupWaitBits(xCreatedEventGroup_WifiConnect,// 事件标志组句柄 
                        WIFI_CONNECTED_BIT, // 等待bit0和bit1被设置 
                        pdFALSE,             //TRUE退出时bit0和bit1被清除,pdFALSE退出时bit0和bit1不清除
                        pdFALSE,             //设置为pdTRUE表示等待bit1和bit0都被设置,pdFALSE表示等待bit1或bit0其中一个被设置
                        portMAX_DELAY);      //等待延迟时间,一直等待 
    if (bits & WIFI_CONNECTED_BIT) 
    {
        //新建socket
        udp_connect_socket = socket(AF_INET, SOCK_DGRAM, 0);                         /*参数和TCP不同*/
        if (udp_connect_socket < 0)
        {
            //新建失败后,关闭新建的socket,等待下次新建
            close(udp_connect_socket);
            return ESP_FAIL;
        }
        //配置连接服务器信息
        udp_client_addr.sin_family = AF_INET;
        udp_client_addr.sin_port = htons(port);
        udp_client_addr.sin_addr.s_addr = inet_addr(ip);
        int len = 0;            //长度
        char databuff[30] = "Hello Server,Please ack!!";    //不管有没有连接先发送一波数据再说
        //测试udp server,返回发送成功的长度
        len = sendto(udp_connect_socket, databuff, 30, 0, (struct sockaddr *) &udp_client_addr,sizeof(udp_client_addr));
        if (len > 0)
        {
        } 
        else 
        {
            close(udp_connect_socket);
            return ESP_FAIL;
        }
        return ESP_OK;
    }
    else
    {
        return ESP_FAIL;
    }
}
/***********************************************************************
* 函数:  
* 描述:   客户端任务
* 参数:
* 返回: 无
* 备注:
************************************************************************/
static void vTaskUdp(void *pvParameters)
{
    int len = 0;            //长度
    uint8_t databuff[512];    //缓存
    //创建udp客户端
    CreateUdpClient(UDP_CLIENT_ADRESS,UDP_CLIENT_PORT);
    unsigned int udpsocklen = sizeof(udp_client_addr);      //地址长度
    for (;;)
    {
        //读取接收数据
        memset(databuff,0,sizeof(databuff));
        len = recvfrom(udp_connect_socket, databuff, sizeof(databuff), 0,(struct sockaddr *) &udp_client_addr, &udpsocklen);
        if (len > 0)//接收到数据
        {
            printf("UDP REV: %s\n",(char *)databuff);
            sendto(udp_connect_socket, databuff, len , 0,(struct sockaddr *) &udp_client_addr, sizeof(udp_client_addr));
        }
        else
        {
            //断开连接
            CreateUdpClient(UDP_CLIENT_ADRESS,UDP_CLIENT_PORT);
            vTaskDelay(500 / portTICK_PERIOD_MS);
        }
        vTaskDelay(50 / portTICK_PERIOD_MS);
    }
}

代码:udp_bsp.h

#ifndef __UDP_BSP_H__
#define __UDP_BSP_H__
#ifdef __cplusplus
extern "C" {
#endif
 //作为UDP CLIENT,255.255.255.255,表示关闭数据
 //如果需要发送到指定IP,这里直接输入对方IP
#define UDP_CLIENT_ADRESS       "255.255.255.255"   
#define UDP_CLIENT_PORT          4000               //UDP客户端端口

#define WIFI_CONNECTED_BIT  BIT0
#define WIFI_FAIL_BIT       BIT1
extern EventGroupHandle_t xCreatedEventGroup_WifiConnect;

void AppTaskCreate(void);


#ifdef __cplusplus
}
#endif
#endif /*#ifndef __UDP_BSP_H__*/

测试时,如果连接不上,先按一下rst按键时

在这里插入图片描述

所有文章源代码:https://download.csdn.net/download/lu330274924/88518092

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值