ESP8266例程解析⑤UDP client and server
阿新 • • 發佈:2018-12-30
一、簡介
- UDP 是 User Datagram Protocol的簡稱,是一種無連線、不可靠的協議,每一個數據報都是一個獨立的資訊,它在網路上以任何可能的路徑傳到目的地,但不保證是否真的傳到目的地、是否過程中真的保證了資料的完整性!
- UDP就好似發簡訊,只管發出去,至於對方是不是空號(網路不可到達)能不能收到(丟包)等並不關心。
- UDP無需等待對面的確認了,再發送資料過去。這執行效率較高,適合要求傳送迅速、資料小的連線!
- 在網路傳輸應用層中,通常使用TCP和UDP這三種協議實現資料的傳輸。在傳輸過程中,需要雙向的通訊連線實現資料的互動。因此,在這雙向鏈路的一端稱之為socket,一個socket有一個IP地址和埠號。
二、UDP client and server
UDP client(8266為UDP客戶端,手機為UDP服務端)
提示:
①.必須要服務端先開啟,也即是手機先開啟服務,設定對應的埠!然後8266開啟UDP客戶端去連線手機,進行通訊。
②.如果沒有設定對埠對應,也會提示手機發送成功,因為UDP協議就是傳送出去,不管是否到達目的地。
UDP client流程分析 (即程式碼分析)
-
8266分割槽初始化
-
設定串列埠
-
WiFi設定模式(station模式)
-
esp8266 station初始化並使能
-
連線路由器
-
回撥定時器函式
回撥函式Check_WifiState
查詢esp8266 station介面連線AP的狀態
設定 ESP8266 傳送 UDP廣播包時,從 station 介面傳送
分配發送空間
設定型別為UDP協議,設定本地埠 目標埠 目標IP地址(廣播 255.255.255.255)
執行接收或者傳送函式
建議UDP連線 傳送測試內容
/** 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; };
程式碼
#include "driver/uart.h" //串列埠0需要的標頭檔案
#include "osapi.h" //串列埠1需要的標頭檔案
#include "user_interface.h" //WIFI連線需要的標頭檔案
#include "espconn.h"//TCP連線需要的標頭檔案
#include "mem.h" //系統操作需要的標頭檔案
struct espconn user_udp_espconn;
os_timer_t checkTimer_wifistate;
void ICACHE_FLASH_ATTR user_udp_sent_cb(void *arg) //傳送
{
os_printf("\r\n傳送成功!\r\n");
}
void ICACHE_FLASH_ATTR user_udp_recv_cb(void *arg, //接收
char *pdata, unsigned short len)
{
os_printf("接收資料:%s", pdata);
//每次傳送資料確保引數不變
user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));
user_udp_espconn.type = ESPCONN_UDP;
user_udp_espconn.proto.udp->local_port = 2000;
user_udp_espconn.proto.udp->remote_port = 8686;
const char udp_remote_ip[4] = { 255, 255, 255, 255 };
os_memcpy(user_udp_espconn.proto.udp->remote_ip, udp_remote_ip, 4);
espconn_sent((struct espconn *) arg, "已經收到啦!", strlen("已經收到啦!"));
}
void Check_WifiState(void)
{
uint8 getState = wifi_station_get_connect_status();
//如果狀態正確,證明已經連線
if (getState == STATION_GOT_IP)
{
os_printf("WIFI連線成功!");
os_timer_disarm(&checkTimer_wifistate);
wifi_set_broadcast_if(0x01); //設定 ESP8266 傳送 UDP廣播包時,從 station 介面傳送
user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));//分配空間
user_udp_espconn.type = ESPCONN_UDP; //設定型別為UDP協議
user_udp_espconn.proto.udp->local_port = 2000; //本地埠
user_udp_espconn.proto.udp->remote_port = 8686; //目標埠
const char udp_remote_ip[4] = { 255, 255, 255, 255 }; //目標IP地址(廣播)
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); //傳送
espconn_create(&user_udp_espconn); //建立 UDP 傳輸
espconn_sent(&user_udp_espconn, "連線伺服器", strlen("連線伺服器"));
}
}
void udp_client_init() //初始化
{
wifi_set_opmode(0x01); //設定為STATION模式 三種模式
struct station_config stationConf;
os_strcpy(stationConf.ssid, "xiaofang"); //改成你要連線的 路由器的使用者名稱
os_strcpy(stationConf.password, "12345678"); //改成你要連線的路由器的密碼
wifi_station_set_config(&stationConf); //設定WiFi station介面配置,並儲存到 flash
wifi_station_connect(); //連線路由器(ESP8266 wifi station 介面連線AP)
os_timer_disarm(&checkTimer_wifistate); //取消定時器定時
os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,
NULL); //設定定時器回撥函式
os_timer_arm(&checkTimer_wifistate, 500, 1); //啟動定時器,單位:毫秒
}
UDP server(手機為UDP客戶端,8266為UDP服務端)
提示:
充當UDP服務端時候,要自身開啟WIFI熱點,等待裝置接入,好比一個閘道器。手機接入8266熱點WiFi時候,注意串列埠發出來的IP地址,此地址是手機要連線的UDP伺服器的地址。
#include "driver/uart.h" //串列埠0需要的標頭檔案
#include "osapi.h" //串列埠1需要的標頭檔案
#include "user_interface.h" //WIFI連線需要的標頭檔案
#include "espconn.h"//TCP連線需要的標頭檔案
#include "mem.h" //系統操作需要的標頭檔案
#include "gpio.h"
struct espconn user_udp_espconn;
static void Inter213_Receive(void *arg, char *pdata, unsigned short len)
{ //接收
os_printf("收到資料:%s\r\n", pdata); // %s,用來輸出一個字串
espconn_sent((struct espconn *) arg, "已經收到", strlen("已經收到"));
}
static void Inter213_Send_Cb(void *arg)
{ //傳送
os_printf("\r\n已傳送\r\n");
}
void Inter213_InitUDP(int32_t Remote_port, uint32_t Local_port)
{
user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp)); //分配空間
user_udp_espconn.type = ESPCONN_UDP; //設定型別為UDP協議
user_udp_espconn.proto.udp->local_port = Local_port; //本地埠
user_udp_espconn.proto.udp->remote_port = Remote_port; //目標埠
espconn_regist_recvcb(&user_udp_espconn, Inter213_Receive); //接收
espconn_regist_sentcb(&user_udp_espconn, Inter213_Send_Cb); //傳送
espconn_create(&user_udp_espconn); //建立UDP傳輸
}
void WIFI_Init()
{
struct softap_config apConfig;
wifi_set_opmode(0x02); //設定為AP模式,並儲存到 flash
apConfig.ssid_len = 8; //設定ssid長度
os_strcpy(apConfig.ssid, "xiaofang"); //設定ssid名字
os_strcpy(apConfig.password, "12345678"); //設定密碼
apConfig.authmode = 3; //設定加密模式
apConfig.beacon_interval = 100; //信標間隔時槽100 ~ 60000 ms
apConfig.channel = 1; //通道號1 ~ 13
apConfig.max_connection = 4; //最大連線數
apConfig.ssid_hidden = 0; //隱藏SSID
wifi_softap_set_config(&apConfig); //設定 WiFi soft-AP 介面配置,並儲存到 flash
}
void udp_services_init() //初始化
{
os_printf("\r\n udp_services_init ... \r\n");
WIFI_Init();
Inter213_InitUDP(8266, 8266); //目標埠,本地埠
}