1. 程式人生 > >使用Arduino開發ESP32(04):UDP通訊使用說明

使用Arduino開發ESP32(04):UDP通訊使用說明

文章目錄

目的

UDP是網路應用中常用的功能,可以算是最簡單的功能了,學會使用UDP就可以開發很多網路應用了。

常規UDP

使用示例

UDP使用比較簡單,直接使用下面程式碼進行測試:

#include <WiFi.h>
#include <WiFiUdp.h> //引用以使用UDP

const char *ssid = "********"
; const char *password = "********"; WiFiUDP Udp; //建立UDP物件 unsigned int localUdpPort = 2333; //本地埠號 void setup() { Serial.begin(115200); Serial.println(); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (!WiFi.isConnected()) { delay(500); Serial.print(".")
; } Serial.println("Connected"); Serial.print("IP Address:"); Serial.println(WiFi.localIP()); Udp.begin(localUdpPort); //啟用UDP監聽以接收資料 } void loop() { int packetSize = Udp.parsePacket(); //獲取當前隊首資料包長度 if (packetSize) //如果有資料可用 { char buf[packetSize]; Udp.read(buf,
packetSize); //讀取當前包資料 Serial.println(); Serial.print("Received: "); Serial.println(buf); Serial.print("From IP: "); Serial.println(Udp.remoteIP()); Serial.print("From Port: "); Serial.println(Udp.remotePort()); Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //準備傳送資料 Udp.print("Received: "); //複製資料到傳送快取 Udp.write((const uint8_t*)buf, packetSize); //複製資料到傳送快取 Udp.endPacket(); //傳送資料 } }

在這裡插入圖片描述

常用方法說明

  • uint8_t begin(uint16_t p)
    uint8_t begin(IPAddress a, uint16_t p)
    啟動監聽某個埠,或者來自某地址傳送給某埠的資料;
  • void stop()
    停止監聽,釋放資源;
  • int beginPacket()
    準備傳送資料包(僅在執行parsePacket()方法且返回值大於0時可用);
  • int beginPacket(IPAddress ip, uint16_t port)
    準備傳送資料包,引數分別為目標IP和目標埠號;
  • size_t write(uint8_t)
    size_t write(const uint8_t *buffer, size_t size)
    複製資料到傳送快取(同一資料包傳送快取最大1460位元組);
  • int endPacket()
    傳送資料;
  • int parsePacket()
    獲取接收資料資訊,如果有資料包可用,則返回隊首資料包長度,否則返回0;
  • int read()
    讀取首位元組資料(僅在執行parsePacket()方法且返回值大於0時可用);
  • int read(unsigned char* buffer, size_t len)
    int read(char* buffer, size_t len)
    讀取資料(僅在執行parsePacket()方法且返回值大於0時可用);
  • int peek()
    讀取首位元組資料,但並不從接收快取中刪除它(僅在執行parsePacket()方法且返回值大於0時可用);
  • void flush()
    清空當前接收快取(僅在執行parsePacket()方法且返回值大於0時可用);
  • IPAddress remoteIP()
    返回遠端地址(僅在執行parsePacket()方法且返回值大於0時可用);
  • uint16_t remotePort()
    單號遠端埠號(僅在執行parsePacket()方法且返回值大於0時可用);

非同步UDP

非同步UDP理論上可以提供比一般UDP更加優異的效能。

使用示例

可以使用下面的程式碼進行測試:

#include <WiFi.h>
#include <AsyncUDP.h> //引用以使用非同步UDP

const char *ssid = "********";
const char *password = "********";

AsyncUDP udp;                     //建立UDP物件
unsigned int localUdpPort = 2333; //本地埠號

unsigned int broadcastPort = localUdpPort;
const char *broadcastData = "broadcast data";
// const uint8_t broadcastData[] = {"broadcast data"};

void onPacketCallBack(AsyncUDPPacket packet)
{
  Serial.print("UDP資料包來源型別: ");
  Serial.println(packet.isBroadcast() ? "廣播資料" : (packet.isMulticast() ? "組播" : "單播"));
  Serial.print("遠端地址及埠號: ");
  Serial.print(packet.remoteIP());
  Serial.print(":");
  Serial.println(packet.remotePort());
  Serial.print("目標地址及埠號: ");
  Serial.print(packet.localIP());
  Serial.print(":");
  Serial.println(packet.localPort());
  Serial.print("資料長度: ");
  Serial.println(packet.length());
  Serial.print("資料內容: ");
  Serial.write(packet.data(), packet.length());
  Serial.println();

  packet.print("reply data");
  broadcastPort = packet.remotePort();
}

void setup()
{
  Serial.begin(115200);
  Serial.println();

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (!WiFi.isConnected())
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected");
  Serial.print("IP Address:");
  Serial.println(WiFi.localIP());

  while (!udp.listen(localUdpPort)) //等待udp監聽設定成功
  {
  }
  udp.onPacket(onPacketCallBack); //註冊收到資料包事件
}

void loop()
{
  delay(5000);

  udp.broadcastTo(broadcastData, broadcastPort); //可以使用該方法廣播資訊

  // IPAddress broadcastAddr((~(uint32_t)WiFi.subnetMask())|((uint32_t)WiFi.localIP())); //計算廣播地址
  // udp.writeTo(broadcastData, sizeof(broadcastData), broadcastAddr, localUdpPort); //廣播資料
}

在這裡插入圖片描述
非同步UDP在收到資料時會觸發事件,比起需要在loop()中查詢獲取資料響應要快很多。

常用方法說明

AsyncUDP類

  • void onPacket(AuPacketHandlerFunctionWithArg cb, void * arg=NULL)
    void onPacket(AuPacketHandlerFunction cb)
    註冊事件,繫結回撥函式;
  • bool listen(const IPAddress addr, uint16_t port)
    bool listen(uint16_t port)
    開啟監聽;
  • void close()
    關閉UDP;
  • size_t writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX);
    size_t write(const uint8_t *data, size_t len)
    size_t write(uint8_t data)
    傳送資料;
  • size_t broadcastTo(uint8_t *data, size_t len, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
    size_t broadcastTo(const char * data, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
    size_t broadcast(uint8_t *data, size_t len)
    size_t broadcast(const char * data)
    廣播資料;

AsyncUDPPacket類

  • uint8_t * data()
    返回資料指標;
  • size_t length()
    返回資料長度;
  • bool isBroadcast()
    查詢是否為廣播資料;
  • bool isMulticast()
    查詢是否為組播地址;
  • IPAddress localIP()
    返回目標(本地)IP;
  • uint16_t localPort()
    返回目標(本地)埠號;
  • IPAddress remoteIP()
    返回遠端IP;
  • uint16_t remotePort()
    返回遠端埠號;
  • size_t read(uint8_t *data, size_t len)
    讀取資料;
  • int read()
    讀取首位元組資料;
  • int peek()
    讀取首位元組資料,但並不從接收快取中刪除它;
  • void flush()
    清空當前接收快取;
  • size_t write(const uint8_t *data, size_t len)
    size_t write(uint8_t data)
    向遠端發資料;

總結

UDP的使用基本上就上面那些了,UDP中還有組播的功能上面沒有介紹,可以參考官方例程和原始碼。
更多內容參考如下:
https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFi
https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP