使用Arduino開發ESP32(04):UDP通訊使用說明
阿新 • • 發佈:2019-01-14
文章目錄
目的
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