授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。

QQ技术互动交流群:ESP8266&32 物联网开发 群号622368884,不喜勿喷

一、你如果想学基于Arduino的ESP8266开发技术

一、基础篇

  1. ESP8266开发之旅 基础篇① 走进ESP8266的世界
  2. ESP8266开发之旅 基础篇② 如何安装ESP8266的Arduino开发环境
  3. ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明
  4. ESP8266开发之旅 基础篇④ ESP8266与EEPROM
  5. ESP8266开发之旅 基础篇⑤ ESP8266 SPI通信和I2C通信
  6. ESP8266开发之旅 基础篇⑥ Ticker——ESP8266定时库

二、网络篇

  1. ESP8266开发之旅 网络篇① 认识一下Arduino Core For ESP8266
  2. ESP8266开发之旅 网络篇② ESP8266 工作模式与ESP8266WiFi库
  3. ESP8266开发之旅 网络篇③ Soft-AP——ESP8266WiFiAP库的使用
  4. ESP8266开发之旅 网络篇④ Station——ESP8266WiFiSTA库的使用
  5. ESP8266开发之旅 网络篇⑤ Scan WiFi——ESP8266WiFiScan库的使用
  6. ESP8266开发之旅 网络篇⑥ ESP8266WiFiGeneric——基础库
  7. ESP8266开发之旅 网络篇⑦ TCP Server & TCP Client
  8. ESP8266开发之旅 网络篇⑧ SmartConfig——一键配网
  9. ESP8266开发之旅 网络篇⑨ HttpClient——ESP8266HTTPClient库的使用
  10. ESP8266开发之旅 网络篇⑩ UDP服务
  11. ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用
  12. ESP8266开发之旅 网络篇⑫ 域名服务——ESP8266mDNS库
  13. ESP8266开发之旅 网络篇⑬ SPIFFS——ESP8266 Flash文件系统
  14. ESP8266开发之旅 网络篇⑭ web配网
  15. ESP8266开发之旅 网络篇⑮ 真正的域名服务——DNSServer
  16. ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新

三、应用篇

  1. ESP8266开发之旅 应用篇① 局域网应用 ——炫酷RGB彩灯
  2. ESP8266开发之旅 应用篇② OLED显示天气屏
  3. ESP8266开发之旅 应用篇③ 简易版WiFi小车

四、高级篇

  1. ESP8266开发之旅 进阶篇① 代码优化 —— ESP8266内存管理
  2. ESP8266开发之旅 进阶篇② 闲聊Arduino IDE For ESP8266配置
  3. ESP8266开发之旅 进阶篇③ 闲聊 ESP8266 Flash
  4. ESP8266开发之旅 进阶篇④ 常见问题 —— 解决困扰
  5. ESP8266开发之旅 进阶篇⑤ 代码规范 —— 像写文章一样优美
  6. ESP8266开发之旅 进阶篇⑥ ESP-specific APIs说明

1. 前言

    前面的博文中,博主讲述的内容基本上都是Tcp以及Http通信的内容,那么我们当然得讲解一下Tcp的另外一个兄弟——UDP。

1.1 TCP与UDP优缺点

  1. TCP是面向连接,也就是发送数据之前是需要建立连接;UDP是面向无连接的,即发送数据之前不需要建立连接。
  2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力做到可靠,即不保证绝对可靠。
  3. UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
  4. 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
  5. TCP对系统资源要求较多,UDP对系统资源要求较少。

UDP 是 User Datagram Protocol 的简称,是一种无连接、不可靠的协议,每一个数据报都是一个独立的信息,它在网络上以任何可能的路径传到目的地,但不保证是否真的传到目的地、是否过程中真的保证了数据的完整性!

UDP就好像无手机时代,你要去探望亲戚,但是你不知道亲戚有没有在家(也就是说可能会丢包);

TCP就好像有手机时代,你要去探望亲戚,你会打电话过去提前沟通好,你会确保亲戚在家里才会买东西过去探望(数据不会丢包);

使用UDP服务,请在代码前加入一下头文件:

#include <WiFiUdp.h>

2. WiFiUDP库

    老规矩,先上一个博主总结的百度脑图:

总体上,根据功能可以把方法分为4大类:

  • 启动UDP服务方法;
  • 处理发送过来的UDP包;
  • 获取UDP client的信息;
  • 发送UDP包;

2.1 启动UDP服务方法

2.1.1 begin —— 开启UDP服务

函数说明:

/**
 * 初始化TCP服务,开始监听特定端口
 * @return  1 表示成功
 *          0 表示没有有效的socket可以用
 */
uint8_t begin(uint16_t port);   

2.1.2 stop —— 停止UDP服务

函数说明:

/**
 * 断开UDP连接
 */
void stop();    

2.2 处理发送过来的UDP包

2.2.1 parsePacket —— 解析UDP数据包

函数说明:

/**
 * 开始处理进来的UDP请求
 * @return  int 返回当前UDP包的大小,如果没有就返回0
 */
int parsePacket();  

注意点:

  • 此方法要在 available、read、peek之前调用(总结来说,就是读取数据之前应该解析数据);

2.2.2 available —— 判断UDP数据包可读大小

函数说明:

/**
 * 返回当前udp包的可读剩余字节数据
 */
int available();    

2.2.3 read —— 读取数据并清除

函数说明:

/**
 * 读取当前udp数据包的一个字节,并从缓冲区清除该字节
 * @return 单字节数据
 */
int read(); 

/**
 * 读取当前udp数据包的len长度的数据,并从缓冲区清除该字节
 * @param buffer 存储数据的内存空间
 * @param len 需要读取的长度
 * @return 读取成功字节数
 */
int read(unsigned char* buffer, size_t len);

注意点:

  • 此方法读取完数据之后会把数据从缓冲区去掉;

2.2.4 peek —— 读取数据

函数说明:

/**
 * 读取当前udp数据包的一个字节
 * @return 单字节数据
 */
int peek(); 

注意点:

  • 此方法读取完数据之后会不会把数据从缓冲区去掉;
  • 建议尽量使用批量处理函数;

2.2.5 flush —— 清除缓冲区

函数说明:

/**
 * 清除缓冲区
 */
void flush();   

2.3 获取UDP 远端的信息

2.3.1 remoteIP —— 远端IP地址

函数说明:

/**
 * 获取发送当前UDP包的主机IP地址
 * @return IPAddress ip地址
 */
IPAddress remoteIP();   

2.3.2 remotePort —— 远端端口

函数说明:

/**
 * 获取发送当前UDP包的主机端口
 * @return uint16_t 端口
 */
uint16_t remotePort();  

2.4 发送UDP包

2.4.1 beginPacket —— 配置ip和port

函数说明:

/**
 * 开始创建需要发送给远端主机的udp包
 * @param ip 远端主机ip地址
 * @param port 远端主机端口号
 * @return 1 创建成功
 *         0 创建失败
 */
int beginPacket(IPAddress ip, uint16_t port);
int beginPacket(const char *host, uint16_t port);

2.4.2 write —— 把数据写入发送缓冲区

函数说明:

/**
 * 写入一字节数据到创建好的udp包
 * @param uint8_t 单字节数据
 * @return 1 写入成功
 *         0 写入失败
 */
size_t write(uint8_t);

/**
 * 写入字节数据到创建好的udp包
 * @param buffer 字节数据缓冲区
 * @return size_t 返回写入成功的字节数
 */
size_t write(const uint8_t *buffer);

/**
 * 写入size字节数据到创建好的udp包
 * @param buffer 字节数据缓冲区
 * @param size 字节数据长度
 * @return size_t 返回写入成功的字节数
 */
size_t write(const uint8_t *buffer, size_t size);

2.4.3 endPacket —— 发送数据

函数说明:

/**
 * 把udp数据包发送出去
 * @param uint8_t 单字节数据
 * @return 1 发送成功
 *         0 发送失败
 */
int endPacket();

3. 实例

3.1 通过UDP收发数据

实例说明

  • ESP8266作为UDP服务端,把电脑UDP客户端发过来的数据打印到串口调试器,并回复应答信息;

源码:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "********";//wifi账号
const char* password = "********";//wifi密码

WiFiUDP Udp;
unsigned int localUdpPort = 4210;  // 本地监听端口
char incomingPacket[255];  // 存储Udp客户端发过来的数据
char  replyPacket[] = "Hi there! Got the message :-)";  // 应答信息

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

  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");

  //启动Udp监听服务
  Udp.begin(localUdpPort);
  //打印本地ip地址,udp client端会使用到
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}

void loop()
{
  //解析Udp数据包
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    // 收到Udp数据包
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    // 读取Udp数据包
    int len = Udp.read(incomingPacket, 255);
    if (len > 0)
    {
      incomingPacket[len] = 0;
    }
    //向串口调试器打印信息
    Serial.printf("UDP packet contents: %s\n", incomingPacket);

    //往udp 远端发送应答信息
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(replyPacket);
    Udp.endPacket();
  }
}

注意点:

  • 为了模拟UDP客户端请求,请下载使用以下软件 Packet Sender

测试结果:

  • ESP8266先开启UDP服务,然后Packet Sender发送UDP数据:

3.2 通过UDP控制LED

实例说明

  • ESP8266作为UDP服务端,把电脑UDP客户端发过来的命令用来控制板载LED灯,其中 LED_ON 表示开灯,LED_OFF表示关灯,操作完毕后需要回复信息;

源码:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char *ssid = "********";     //wifi名称
const char *password = "********"; //wifi密码

WiFiUDP Udp;
unsigned int localUdpPort = 4210; // 本地端口号
char incomingPacket[255];         // 接收缓冲区

void setup()
{
  //以下为基本功能初始化,初始化串口和网络和LED
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  Serial.println();
  Serial.printf("Connecting to %s ", ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");

  //以下开启UDP监听并打印输出信息
  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}

void loop()
{
  int packetSize = Udp.parsePacket(); //获取当前队首数据包长度
  if (packetSize)  // 有数据可用
  {
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket, 255); // 读取数据到incomingPacket
    if (len > 0)                             // 如果正确读取
    {
      incomingPacket[len] = 0; //末尾补0结束字符串
      Serial.printf("UDP packet contents: %s\n", incomingPacket);

      if (strcmp(incomingPacket, "LED_OFF") == 0) // 命令LED_OFF
      {
        digitalWrite(LED_BUILTIN, HIGH); // 熄灭LED
        sendCallBack("LED has been turn off");
      }
      else if (strcmp(incomingPacket, "LED_ON") == 0) // 如果收到LED_ON
      {
        digitalWrite(LED_BUILTIN, LOW); // 点亮LED
        sendCallBack("LED has been turn on");
      }
      else // 如果非指定消息
      {
        sendCallBack("Command Error!");
      }
    }
  }
}

/**
 * 发送响应信息
 */
void sendCallBack(const char *buffer){
   Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
   Udp.write(buffer); //回复内容
   Udp.endPacket();
}

测试结果:

  • ESP8266先开启UDP服务,然后Packet Sender发送UDP命令:

4. 总结

使用Arduino for esp8266可以非常简单实现UDP通讯过程。最重要需要记住的一点,那就是UDP面向无连接,发送出去的数据不会理会是否被收到。

ESP8266开发之旅 网络篇⑩ UDP服务的更多相关文章

  1. ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  2. ESP8266开发之旅 网络篇⑦ TCP Server & TCP Client

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  3. ESP8266开发之旅 网络篇⑧ SmartConfig——一键配网

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  4. ESP8266开发之旅 网络篇⑨ HttpClient——ESP8266HTTPClient库的使用

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  5. ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  6. ESP8266开发之旅 网络篇⑫ 域名服务——ESP8266mDNS库

    1. 前言     前面的博文中,无论是作为client端还是server端,它们之间的通信都是通过具体的IP地址来寻址.通过IP地址来寻址,本身就是一个弊端,用户怎么会去记住这些魔法数字呢?那么有没 ...

  7. ESP8266开发之旅 网络篇⑬ SPIFFS——ESP8266 SPIFFS文件系统

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  8. ESP8266开发之旅 网络篇⑮ DNSServer——真正的域名服务

    1. 前言     Arduino for esp8266中有两个DNS服务相关的库: ESP8266mDNS库 这个库是mDNS库,使用这个库的时候ESP8266可以在AP模式或是以STA模式接入局 ...

  9. ESP8266开发之旅 网络篇⑭ web配网

    1. 前言     目前,市面上流行多种配网方式: WIFI模块的智能配网(SmartConfig以及微信AirKiss配网) SmartConfig 配网方式 请参考博主之前的博文 ESP8266开 ...

随机推荐

  1. 针对媒体不实报道误导大众--抹黑C#工资垫底

    最近注意到一些媒体故意抹黑C# 工资垫底,参见 https://www.toutiao.com/i6741889572931633668/: 通过搜索引擎搜索<编程语言薪酬排行:Python薪资 ...

  2. electron教程(一): electron的安装和项目的创建

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(二): http服务器, ws服务器, 进程管理 electron教程(三): 使 ...

  3. C语言入门-函数

    一.初见函数 求出1到10.20到30和35到45的三个的和 #include <stdio.h> // 定义一个函数 void sum(int begin, int end) { int ...

  4. RecyclerView实现Gallery画廊效果

    使用RecyclerView实现一个画廊效果,主要是使用support库中最新加入的PagerSnapHelper类,通过计算滑动偏移来计算scale的值. 基本实现 首先需要为RecyclerVie ...

  5. Kotlin学习系列(一)

    基本类型 在Kotlin中任何事物都是对象你可以在任何变量上调用相应的方法或属性.Kotlin的一些内置类型如下: Number: 包含整形与浮点型 Character: 字符(Chat) Boole ...

  6. Java Map知识点

    1.遍历 java遍历Map的方式有多种,一下以代码示例来说明使用: Map<String, String> tmap = new HashMap<String, String> ...

  7. springboot 使用freemarker自定义标签

    1.pom依赖引入 <dependencies> <dependency> <groupId>org.springframework.boot</groupI ...

  8. JS 时间格式 相互转化

    1. 时间字符串格式 var dateString1 = '2016-06-15 10:22:00'; var dateString2 = '2016/06/15 10:22:00'; var dat ...

  9. Python IAQ中文版 - Python中少有人回答的问题

    Python中少有人回答的问题 The Python IAQ: Infrequently Answered Questions 1 Q: 什么是"少有人回答的问题(Infrequently ...

  10. HttpClient连接池的一些思考

    前言 使用apache的httpclient进行http的交互处理已经很长时间了,而httpclient实例则使用了http连接池,想必大家也没有关心过连接池的管理.事实上,通过分析httpclien ...