嵌入式系统与单片机|技术阅读
登录|注册

您现在的位置是:嵌入式系统与单片机 > 技术阅读 > ESP8266入门(三)UDP通信

ESP8266入门(三)UDP通信

上一篇我们讲了esp8266连接路由器,这一篇就讲一下局域网中的UDP通信。


1、UDP简介


UDP 是User Datagram Protocol的简称。

翻译成中文是用户数据包协议,是OSI(Open System Interconnection开放式系统互联) 中一种无连接的传输层协议。

提供简单不可靠信息传送服务( 会丢数据包)

UDP协议位于传输层,是IP协议的上一层。UDP具有不提供数据包分组和不能对数据包进行排序的缺点。也就是当报文发送之后,是无法得知其是否安全完整到达的。

不过UDP协议也有他的优点,在许多应用中只支持UDP,如:多媒体数据流,因为不产生任何额外的数据,即使有破坏的包也不进行重发。

当强调传输性能而不是传输的完整性时,UDP是最好的选择。


2、esp8266进行UDP传输的几个结构体


下面我们讲一下怎么使用esp8266进行UDP传输数据。

主要用到下面的这个结构体struct espconn,如下

/** A espconn descriptor */struct espconn { /** type of the espconn (TCP, UDP) */ enum espconn_type type; /** current state of the espconn */ enum espconn_state state; union { esp_tcp *tcp; esp_udp *udp; } proto;    /** A callback function that is informed about events    for this espconn */ espconn_recv_callback recv_callback; espconn_sent_callback sent_callback; uint8 link_cnt; void *reverse;};
  • type设置成UDP

  • proto使用联合体中的esp_udp *udp

  • recv_callback为接收回调函数

  • sent_callback发送数据回调函数

这个结构体好像没有设置目标IP和端口,那到底往哪发呢?

那这就需要下面这个结构体了,

这个就是上面proto指针指向的结构体esp_udp

typedef struct _esp_udp { int remote_port; int local_port; uint8 local_ip[4]; uint8 remote_ip[4];} esp_udp;
  • remote_port为远程端口

  • local_port为本地端口

  • local_ip为本地IP(即8266自己的IP)

  • remote_ip为远程IP(发送到目标服务器的 IP)


3、实现UDP通信函数


有了上面的两个结构体,我们就可以写UDP通信的程序了,代码如下

void ICACHE_FLASH_ATTR UDP_conn_init() { wifi_set_broadcast_if (STATIONAP_MODE);
user_udp_espconn.type = ESPCONN_UDP; ||分配内存给proto.udp指针 user_udp_espconn.proto.udp = (esp_udp*) os_zalloc(sizeof(esp_udp)); user_udp_espconn.proto.udp->local_port = 2525; user_udp_espconn.proto.udp->remote_port = 1112; ||用于存放远程IP地址  const char udp_remote_ip[4] = { 1921680104 };  os_memcpy(&user_udp_espconn.proto.udp->remote_ip, udp_remote_ip, 4); ||接收回调函数 espconn_regist_recvcb(&user_udp_espconn, user_udp_recv_cb);   ||发送回调函数 espconn_regist_sentcb(&user_udp_espconn, user_udp_sent_cb);   ||创建UDP连接 espconn_create(&user_udp_espconn);   ||发送数据  user_udp_send(); }

此函数在路由器连接成功之后调用。

避坑指南:

注意第一条语句,

wifi_set_broadcast_if (STATIONAP_MODE);

必须的加上,否则会接收不到数据,

为什么会接收不到数据呢?

编程指南上有讲,大家可以看下,我也把他贴到下面了,如图:

  • UDP广播包居然默认是从soft-AP发送,而且仅从station发还会影响soft-AP功能,所以我们直接设置成3 station和soft-AP均发送(STATIONAP_MODE


两个回调函数和发送函数也贴到下面

os_timer_t test_timer;||UDP发送函数void ICACHE_FLASH_ATTR user_udp_send(void){ char yladdr[6]; ||将获取的MAC地址格式化输出到一个buffer里面  char Buffer[40]={0};  ||获取MAC地址  wifi_get_macaddr(STATION_IF,yladdr);  ||格式化MAC地址  os_sprintf(Buffer,"ESP8266的MAC地址为"MACSTR"!!!\r\n",        MAC2STR(yladdr));  espconn_sent(&user_udp_espconn,Buffer,os_strlen(Buffer));}
||发送回调函数void ICACHE_FLASH_ATTR user_udp_sent_cb(void *arg){ ||定时发送    os_timer_disarm(&test_timer);    os_timer_setfn(&test_timer,user_udp_send,NULL); os_timer_arm(&test_timer,1000,NULL);//定1秒钟发送一次}
||接收回调函数void ICACHE_FLASH_ATTR user_udp_recv_cb(void *arg, char *pdata,unsigned short len){  char temp[128]; os_sprintf(temp,"UDP recive:%s",pdata);  ||UDP接收到的数据打印出来  os_printf("%s",temp);    }


编译、下载程序,执行如下图;

  • 注意两个端口要和程序中的对应,电脑的本地端口就是8266的远端端口。


好了,UDP实验就算成功了,

可是好像还是有点疑问,

UDP协议不是一种无连接的传输层协议吗?

那为啥在局域网内还要指定IP呢?

其实,也可以不指定IP,

只要把8266的远端ip设置成255.255.255.255就可以了,

这样局域网内的服务器就都可以收到数据了(注意端口要一致)

你也可以试试。

(* ̄︶ ̄)



原创不易,如果你喜欢我的公众号、觉得我 文章对你有所启发,

请务必“点赞、收藏、转发”,这对我很重要,谢谢!

欢迎订阅    嵌入式小书虫