程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

ESP——UDP

balukai 2025-01-05 15:45:14 文章精选 7 ℃

UDP简介

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

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

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

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

流程

1. 创建socket

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

2. 发送数据

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

3. 接收数据

使用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));

}

运行结果




最近发表
标签列表