使用Arduino开发ESP32(04):UDP通讯使用说明

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Naisu_kun/article/details/86300456

目的

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

猜你喜欢

转载自blog.csdn.net/Naisu_kun/article/details/86300456