1. 程式人生 > >ESP8266例程解析⑤UDP client and server

ESP8266例程解析⑤UDP client and server

一、簡介

  1. UDP 是 User Datagram Protocol的簡稱,是一種無連線、不可靠的協議,每一個數據報都是一個獨立的資訊,它在網路上以任何可能的路徑傳到目的地,但不保證是否真的傳到目的地、是否過程中真的保證了資料的完整性!
  2. UDP就好似發簡訊,只管發出去,至於對方是不是空號(網路不可到達)能不能收到(丟包)等並不關心。
  3. UDP無需等待對面的確認了,再發送資料過去。這執行效率較高,適合要求傳送迅速、資料小的連線!
  4. 在網路傳輸應用層中,通常使用TCP和UDP這三種協議實現資料的傳輸。在傳輸過程中,需要雙向的通訊連線實現資料的互動。因此,在這雙向鏈路的一端稱之為socket,一個socket有一個IP地址和埠號。

二、UDP client and server

UDP client(8266為UDP客戶端,手機為UDP服務端)

提示:
①.必須要服務端先開啟,也即是手機先開啟服務,設定對應的埠!然後8266開啟UDP客戶端去連線手機,進行通訊。
②.如果沒有設定對埠對應,也會提示手機發送成功,因為UDP協議就是傳送出去,不管是否到達目的地。

UDP client流程分析 (即程式碼分析)

  1. 8266分割槽初始化

  2. 設定串列埠

  3. WiFi設定模式(station模式)

  4. esp8266 station初始化並使能

  5. 連線路由器

  6. 回撥定時器函式

    回撥函式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);		//目標埠,本地埠

}