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