ESP32编程笔记(7)——UDP通讯

本文介绍了UDP(用户数据报协议)的基本概念,包括其无连接特性、数据传输过程,以及在ESP32中的应用示例,涉及socket创建、数据发送与接收,以及IP地址处理函数如inet_aton和inet_ntoa的使用。
摘要由CSDN通过智能技术生成

UDP简介

  1. UDP是无连接的,即发送数据之前不需要建立连接

  2. UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。

  3. UDP支持一对一、一对多、多对一、多对多的交互通信。

  4. UDP的首部开销小,只有8字节,比TCP的还要短。

流程

  1. 创建socket

使用socket()函数创建socket套接字

  1. 发送数据

使用sendto()函数向目标主机发送数据

  1. 接收数据

使用recvfrom()接收数据,如果没有接收到数据,程序会一直阻塞到这里。

socket(套接字)实质上提供了进程通信的端点,进程通信之前,双方首先必须建立各自的端点,否则是没有办法通信的,通过socket将ip地址和端口绑定之后,客户端就可以和服务器通信了。当我们访问套接字时,需要访问文件一样使用 文件描述符

int socket(int domain,int type,int product)

参数:

domain:通信域,确定通讯特性,包括地址格式

|| 描述 |

| AF_INET | ipv4因特网域 |

| AF_INET6 | ipv6因特网域 |

| AF_UNIX | UNIX域 |

| AF_UNSPEC | 未指定 |

type:套接字类型

| type | 描述 |

| SOCK_DGRAM | 长度固定的,无连接的不可靠报文输出 |

| SOCK_RAW | ip协议的数据端口 |

| SOCK_SEQPACKET | 长度固定,有序,可靠面向连接报文传递 |

| SOCK_STREAM | 有序,可靠,双向的面向连接的字节流|

protocol:执行相应的传输协议,也就是诸如TCP或UDP协议等等,系统系统对每一个协议簇类型提供了一个默认的协议,我们通过把protocol设置为0来使用这个默认的值。

返回值:

成功返回套接字文件描述符。

失败返回-1.

ip地址

在socket程序设计中struct sockaddr_in(或者struct sockaddr)用于记录网络地址。

struct sockaddr_in{

short sin_family; //协议簇

unsigned short int sin_port; //端口号

struct in_addr sin_addr; //协议簇特定地址 ip地址

uunsigned char sin_zero; //0

}

typedef struct in_addr{

union{

struct{

unsigned char s_b1;

s_b2;

s_b3;

s_b4;

}S_un_b;

struct{

unsigned short s_w1;

s_w2;

}S_un_w;

unsigned long s_addr;

}S_un

}IN_ADDR

ip地址通常由数字加点(192.168.1.1)的形式表示,而在struct in_addr中的ip地址是由32位的整数来表示的,为了转换我们可以使用两个函数

int inet_aton(const char *cp, struct in_addr *inp)

char *inet_ntoa(struct in_addr in)

inet_aton是将a.b.c.d形式的ip转换为32位的ip,存储在inp指针里

inet_ntoa是将32位的ip地址转换为a.b.c.d的形式。

不同类型的CPU对变量得到字节存储顺序可能不同,有的系统可能是高位在前,低位在后,而有的系统是低位在前,高位在后,而网络传输的数据顺序一定是统一的,所以当内部字节存储顺序和网络字节序不同时,一定要进行转换。 网络序都是大端

htons把unsigned short类型从主机序转换为网络序

htonl把unsigned long类型从主机序转换为网络序

ntons把unsigned short类型从网络序转换为主机序

ntol把unsigned long类型从网络序转换为主机序

实例

#include <stdio.h>

#include <string.h>

#include "esp_system.h"

#include "freertos/FreeRTOS.h"

#include "freertos/task.h"

#include "freertos/event_groups.h"

#include "esp_event.h"

#include "esp_log.h"

#include "nvs_flash.h"

#include "esp_wifi.h"

#include "esp_netif.h"

#include "sys/socket.h"

#include "netinet/in.h"

#include <lwip/netdb.h>

static const char* TAG = "UDP";

const char *payload = "this is from esp32";

static void System_Init(void);

static void WiFi_Init(void);

static void event_handler(void *arg,esp_event_base_t event_base, int32_t event_id, void *data);

void create_udp_clent(void);

void app_main(){

System_Init();

WiFi_Init();

}

void create_udp_clent(){

char rx_buf[128];

struct sockaddr_in socket_addr;

socket_addr.sin_addr.s_addr = inet_addr("192.168.8.104");

socket_addr.sin_family = AF_INET;

socket_addr.sin_port = htons(7778);

int sock = socket(AF_INET, SOCK_DGRAM,0);

if(sock < 0){

ESP_LOGE(TAG, "Unable to create socket");

close(sock);

return;;

}

ESP_LOGI(TAG,"socket cerated");

while(1){

int err = sendto(sock, payload,strlen(payload),0, (struct sockaddr *)&socket_addr, sizeof(socket_addr));

if(err < 0){

ESP_LOGI(TAG, "sendto error");

close(sock);

break;

}

ESP_LOGI(TAG,"message send");

struct sockaddr_in source_addr;

socklen_t socklen = sizeof(source_addr);

memset(rx_buf,0,sizeof(rx_buf));

int len = recvfrom(sock,rx_buf,sizeof(rx_buf),0,(struct sockaddr*)&source_addr,&socklen);

if(len <0){

ESP_LOGE(TAG, "recvfrom failed");

close(sock);

break;

}else{

rx_buf[len] = 0;

ESP_LOGI(TAG,"recv: %s",rx_buf);

}

//vTaskDelay(500/ portTICK_PERIOD_MS);

}

vTaskDelete(NULL);

}

static void event_handler(void *arg,esp_event_base_t event_base, int32_t event_id, void *data){

if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START){

ESP_LOGI(TAG, "wifi start");

esp_wifi_connect();

}else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED){

ESP_LOGI(TAG,"wifi event sta disconnected");

esp_wifi_connect();

}else if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED){

ESP_LOGI(TAG,"wifi event connect");

}else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP){

retry_times = 0;

ip_event_got_ip_t* event = (ip_event_got_ip_t*)data;

ESP_LOGI(TAG, "got ip:" IPSTR,IP2STR(&event->ip_info.ip));

xTaskCreate(&create_udp_clent,"task1",4096,NULL,3,NULL);

}

}

static void System_Init(){

esp_err_t ret = nvs_flash_init();

if(ret == ESP_ERR_NVS_NEW_VERSION_FOUND || ret == ESP_ERR_NVS_NO_FREE_PAGES){

ESP_ERROR_CHECK(ret);

ret = nvs_flash_init();

}

ESP_ERROR_CHECK(ret);

}

static void WiFi_Init(){

ESP_ERROR_CHECK(esp_netif_init());

ESP_ERROR_CHECK(esp_event_loop_create_default());

esp_netif_create_default_wifi_sta();

esp_event_handler_instance_t esp_any_id;

esp_event_handler_instance_t esp_ip_id;

ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL,&esp_any_id));

ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL,&esp_ip_id));

wifi_init_config_t cnf = WIFI_INIT_CONFIG_DEFAULT();

ESP_ERROR_CHECK(esp_wifi_init(&cnf));

ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

wifi_config_t cof = {

.sta = {

.ssid = "",

.password="",

.threshold.authmode=WIFI_AUTH_WPA2_PSK

}

};

ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &cof));

ESP_ERROR_CHECK(esp_wifi_start());

ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT,ESP_EVENT_ANY_ID,&esp_any_id));

ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT,IP_EVENT_STA_GOT_IP,&esp_ip_id));

}

运行结果

在这里插入图片描述

在这里插入图片描述

网络调试助手获取
了解更多 blog点bkstudy点top

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CeHi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值