一般情况下,IOT设备(针对wifi设备)在智能化过程中需要连接到家庭路由。但在此之前,需要将wifi信息(通常是ssid和password,即名字和密码)发给设备,这一步骤被称为配网。移动设备如Android、iOS等扮演发送wifi信息的角色,简单来说就是移动应用要与IOT设备建立通信,进而交换数据。针对配网这一步骤,市面上一般有两种做法:

  • AP连接方式:IOT设备发出AP(Access Point,可理解为路由器,可发出wifi)信息;移动设备STA(Station,可以连接wifi)连接到IOT设备AP,接着就可以发送wifi(家庭路由的wifi)信息给设备了。另外,也可互换角色,及移动设备释放热点,IOT设备进行连接。
  • SmartConfig(一键配置)方式:不需要建立连接,移动设备将wifi信息(需提前获取)写入数据包,组播循环发出此数据包;IOT设备处于监听所有网络的模式,接收到UDP包后解析出wifi信息拿去连网。

可以发现,SmartConfig不需建立连接,步骤较少,实现起来也较容易,并且用户也无需进行过多的操作。本文的IOT设备基于ESP32开发板,解释原理及实现如何通过Android APP发出UDP包实现SmartConfig。知识点:计算机网络、UDP、组播、DatagramSocket ...

一、网络知识回顾

计算机网络分层结构如下:

  • 应用层:体系中的最高层。任务是通过应用程序间的交互来完成特定网络应用。不同的网络应用对应不同的协议:如HTTPDNSSMTP。其交互的数据单元称为报文。
  • 运输层:复杂向两台主机中进程直接的通信提供通用的数据传输服务,使用端口作为向上传递的进程标识,主要有TCP和UDP。
  • 网络层:负责为分组交换网络上的不同主机提供通信服务,使用IP协议。
  • 网络接口层:包括数据链路层和物理层,传输单位分别是帧和比特。

1. IP协议

IP(Internet Protocol)协议是网络层的主要协议。其版本有IPv4(32位)、IPv6(128位)。与IP协议配套使用的还有地址解析协议(ARP)、网际控制报文协议(ICMP,重要应用即常见的PING,测试连通性)、网际组管理协议(IGMP)。

IP数据报格式,由首部和数据部分两部分组成:



IP地址分类如下:

1.1 两级IP地址

IP地址是每一台主机唯一的标识符,由网络号和主机号组成。A、B、C三类均为单播地址(一对一),D类为多播地址(一对多)。

1.2 三级IP地址

在两级中新增了子网号字段,也称为划分子网。其方法是从主机号借用若干位作为子网号。

子网掩码:是一个网络或子网的重要属性,可通过子网掩码计算出目的主机所处于哪一个子网。若没有划分子网,则使用默认子网掩码(A类255.0.0.0、B类255.255.0.0、C类255.255.255.0)

1.3 无分类编址

无分类编址(CIDR)也称为构造超网,使用网络前缀+主机号规则,并使用斜线标明前缀位数,如:

128.15.34.77/20
1.4 IP多播

多播又称为组播,提供一对多的通信,大大节约网络资源。IP数据报中不能写入某一个IP地址,需写入多播组的标识符(需要接收的主机与此标识符关联)。D类地址即为多播组的标识符,所以多播地址(D类)只能作为目的地址。分为本局域网上的硬件多播、互联网多播两种。

多播使用到的协议

  • IGMP(网际组管理协议):让连接在本地局域网上的多播路由器(能够运行多播协议的路由器)知道本局域网上是否有主机(进程)参加或退出了某个多播组。
  • 多播路由选择协议:用于多播路由器之间的协同工作,以便让多播数据报以最小的代价传输。

2. UDP协议

运输层向上面的应用层提供通信服务,通信的端点并不是主机而是主机中进程,使用协议端口号标识进程(如HTTP为80)。UDP协议是运输层中重要的两个协议之一。

  • UDP是无连接的
  • UDP使用尽最大努力交付,不保证可靠交付
  • UDP是面向报文的
  • UDP没有拥塞控制
  • UDP支持一对一,一对多,多对一和多对多
  • UDP首部开销小

二、Java中的UDP

1. Socket

socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。简单来说,socket是一种接口,对传输层(TCP/UPD协议)进行了的封装。

socket通信

  • TCP socket:需建立连接,TCP三次握手,基于流的通信(InputStrea和OutputStream)
  • UDP socket:无需建立连接,基于报文的通信。可以组播的形式发出报文,适合本场景中的配网步骤。

2. Java中的socket

2.1 类解释

Java为Socket编程封装了几个重要的类(均为客户端-服务端模式):

Socket

实现了一个客户端socket,作为两台机器通信的终端,默认采用TCP。connect()方法请求socket连接、getXXXStream()方法获取输入/出流、close()关闭流。

ServerSocket

实现了一个服务器的socket,等待客户端的连接请求。bind()方法绑定一个IP地址和端口、accept()方法监听并返回一个Socket对象(会阻塞)、close()关闭一个socket

SocketAddress # InetSocketAddress

前者是一个抽象类,提供了一个socket地址,不关心传输层协议;后者继承自前者,表示带有IP地址和端口号的socket地址。

DatagramSocket

实现了一个发送和接收数据报的socket,使用UDP。send()方法发送一个数据报(DatagramPacket)、receive()方法接收一个数据报(一直阻塞接至收到数据报或超时)、close()方法关闭一个socket。

DatagramPacket

使用DatagramSocket时的数据报载体。

2.2 UDP实例

SmartConfig采用UDP实现,所以在前述知识的基础下,先编写一个例子熟悉java udp的使用,首先建立服务端的代码:

public class UDPServer {
/**
* 设置缓冲区的长度
*/
private static final int BUFFER_SIZE = 255;
/**
* 指定端口,客户端需保持一致
*/
private static final int PORT = 8089; public static void main(String[] args) {
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket(PORT);
DatagramPacket datagramPacket = new DatagramPacket(new byte[BUFFER_SIZE], BUFFER_SIZE);
while (true) {
// 接收数据报,处于阻塞状态
datagramSocket.receive(datagramPacket);
System.out.println("Receive data from client:" + new String(datagramPacket.getData()));
// 服务器端发出响应信息
byte[] responseData = "Server response".getBytes();
datagramPacket.setData(responseData);
datagramSocket.send(datagramPacket);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (datagramSocket != null) {
datagramSocket.close();
}
}
}
}

客户端发出数据报:

public class UDPClient {
/**
* 指定端口,与服务端保持一致
*/
private static final int PORT = 8089;
/**
* 超时重发时间
*/
private static final int TIME_OUT = 2000;
/**
* 最大重试次数
*/
private static final int MAX_RETRY = 3; public static void main(String[] args) throws IOException {
try {
byte[] sendMsg = "Client msg".getBytes();
// 创建数据报
DatagramSocket socket = new DatagramSocket();
// 设置阻塞超时时间
socket.setSoTimeout(TIME_OUT);
// 创建server主机的ip地址(此处使用了本机地址)
InetAddress inetAddress = InetAddress.getByName("192.168.xxx.xxx");
// 发送和接收的数据报文
DatagramPacket sendPacket = new DatagramPacket(sendMsg, sendMsg.length, inetAddress, PORT);
DatagramPacket receivePacket = new DatagramPacket(new byte[sendMsg.length], sendMsg.length);
// 数据报文可能丢失,设置重试计数器
int tryTimes = 0;
boolean receiveResponse = false;
// 将数据报文发送出去
socket.send(sendPacket);
while (!receiveResponse && (tryTimes < MAX_RETRY)) {
try {
// 阻塞接收数据报文
socket.receive(receivePacket);
// 检查返回的数据报文
if (!receivePacket.getAddress().equals(inetAddress)) {
throw new IOException("Unknown server's data");
}
receiveResponse = true;
} catch (InterruptedIOException e) {
// 重试
tryTimes++;
System.out.println("TimeOut, try " + (MAX_RETRY - tryTimes) + " times");
}
}
if (receiveResponse) {
System.out.println("Receive from server:" + new String(receivePacket.getData()));
} else {
System.out.println("No data!");
}
socket.close();
} catch (SocketException e) {
e.printStackTrace();
}
}
}

运行结果:



* 发现客户端收到的数据被截断了,这是因为没有重置接收包的长度,在服务端datagramPacket.setLength()可解决。

三、SmartConfig

根据前面的socket相关应用,基本想到如何实现一键配置。在实际应用中,原理一样,只是增加了组播(这一点需要和IOT设备端共同确定,数据的格式也需协定)。在实现中,需要针对不同IP组播地址发出循环的UDP报文,增加设备端接收到的可能性;同时APP也要开启服务端程序监听发出数据报的响应,以此更新UI或进行下一步的数据通信。相关核心代码如下:

// 对每一个组播地址循环发出报文
while (!mIsInterrupt && System.currentTimeMillis() - currentTime < mParameter
.getTimeoutGuideCodeMillisecond()) {
mSocketClient.sendData(gcBytes2,
mParameter.getTargetHostname(),
mParameter.getTargetPort(),
mParameter.getIntervalGuideCodeMillisecond());
// 跳出条件,发出UDP报文达到一定时间
if (System.currentTimeMillis() - startTime > mParameter.getWaitUdpSendingMillisecond()) {
break;
}
}

组播地址设置:

public String getTargetHostname() {
if (mBroadcast) {
return "255.255.255.255";
} else {
int count = __getNextDatagramCount();
return "234." + (count + 1) + "." + count + "." + count;
}
}

完整代码省略(利益相关,代码匿了^_^),基本思路很简单。最终的实现是IOT设备收到UDP发出的wifi信息,并以此成功连接wifi,连接服务器,进而绑定账号。

IOT设备SmartConfig实现的更多相关文章

  1. Win10 IoT C#开发 5 - 操作 IoT 设备内嵌 SQLite 数据库 CURD

    Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 前几章我 ...

  2. 操作 IoT 设备内嵌 SQLite

    Win10 IoT C#开发 5 - 操作 IoT 设备内嵌 SQLite 数据库 CURD   Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本 ...

  3. 恶意软件Mirai换了个马甲 瞄上我国2亿多台IoT设备

    恶意软件Mirai换了个马甲 瞄上我国2亿多台IoT设备   想要起来时,一种沉重感阻碍着他,这是一种安全感:感觉到一张床为他铺好了,而且只属于他:想要静卧时,一种不安阻碍着他,把他从床上赶起来,这是 ...

  4. 省钱版----查找 IoT 设备TTL线序__未完待续

    作者:仙果 原文来自:省钱版—-查找 IoT 设备TTL线序 省钱版----查找 IoT 设备TTL线序__未完待续 缘由 在IoT固件调试分析的过程中,建议首先在IoT设备的板子上焊接调试线,这是能 ...

  5. Remaiten-一个以路由器和IoT设备为目标的Linux bot

    Remaiten-一个以路由器和IoT设备为目标的Linux bot ESET的研究人员正在积极地检测以嵌入式系统为攻击目标的木马,受影响的有路由器,网关和无线访问点.近期,我们已经发现了一个相关的b ...

  6. 安天透过北美DDoS事件解读IoT设备安全——Mirai的主要感染对象是linux物联网设备,包括:路由器、网络摄像头、DVR设备,入侵主要通过telnet端口进行流行密码档暴力破解,或默认密码登陆,下载DDoS功能的bot,运行控制物联网设备

    安天透过北美DDoS事件解读IoT设备安全 安天安全研究与应急处理中心(安天CERT)在北京时间10月22日下午启动高等级分析流程,针对美国东海岸DNS服务商Dyn遭遇DDoS攻击事件进行了跟进分析. ...

  7. IoT设备程序开发及编译环境搭建初体验

    引言 Mirai事件一经曝出,立即引领了一轮研究IoT设备的热潮.目前,对Mirai的报告大多只是在对其功能实现上的介绍,却很少提及如何实现IoT设备程序开发的测试环境.本文在对Mirai的源码研究的 ...

  8. IOT设备的7大安全问题

    IOT设备的7大安全问题 串口安全 IOT设备一般包含各类串口,并且这些串口缺乏认证机制.一旦暴露给了hacker,hacker可以很容易的查找敏感信息和dump固件,从而导致各类安全问题.建议厂家在 ...

  9. IoT设备上的恶意软件——通过漏洞、弱密码渗透

    2018年,是 IoT 高速发展的一年,从空调到电灯,从打印机到智能电视,从路由器到监控摄像头统统都开始上网.随着5G网络的发展,我们身边的 IoT 设备会越来越多.与此同时,IoT 的安全问题也慢慢 ...

随机推荐

  1. 跨域解决方案 - node 转发

    目录 1. 定义 2. 代理转发 3. node 转发解决跨域问题 4. 代码演示 5. 参考地址 1. 定义 当用户需要请求数据时, 用户向前端服务器发送请求, 然后前端服务器接收请求之后向后端服务 ...

  2. 结合 AOP 轻松处理事件发布处理日志

    结合 AOP 轻松处理事件发布处理日志 Intro 前段时间,实现了 EventBus 以及 EventQueue 基于 Event 的事件处理,但是没有做日志(EventLog)相关的部分,原本想增 ...

  3. Java实现 蓝桥杯 算法提高 欧拉函数(数学)

    试题 算法提高 欧拉函数 问题描述 老师出了一道难题,小酱不会做,请你编个程序帮帮他,奖金一瓶酱油: 从1-n中有多少个数与n互质? |||||╭══╮ ┌═════┐ ╭╯让路║═║酱油专用车║ ╰ ...

  4. Java实现 LeetCode 710 黑名单中的随机数(黑白名单)

    710. 黑名单中的随机数 给定一个包含 [0,n ) 中独特的整数的黑名单 B,写一个函数从 [ 0,n ) 中返回一个不在 B 中的随机整数. 对它进行优化使其尽量少调用系统方法 Math.ran ...

  5. Java实现 LeetCode 273 整数转换英文表示

    273. 整数转换英文表示 将非负整数转换为其对应的英文表示.可以保证给定输入小于 231 - 1 . 示例 1: 输入: 123 输出: "One Hundred Twenty Three ...

  6. Zabbix+Orabbix监控oracle数据库表空间

    Orabbix 是设计用来为 zabbix 监控 Oracle 数据库的插件,它提供多层次的监控,包括可用性和服务器性能指标. 它提供了从众多 oracle 实例采集数据的有效机制,进而提供此信息的监 ...

  7. 【微信H5】 Redirect_uri参数错误解决方法

    1 https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx14127af0bc9fd367&redirect_uri=http ...

  8. scws中文分词安装和使用

    一.下载源码 wget http://www.xunsearch.com/scws/down/scws-1.2.3.tar.bz2 tar xvjf scws-1.2.3.tar.bz2 二.执行配置 ...

  9. 多线程实现tcp聊天服务器

    多线程tcp  server & client tcp服务端(多线程): from socket import * from threading import Thread def clien ...

  10. @uoj - 164@ 【清华集训2015】V

    目录 @description@ @solution@ @accepted code@ @details@ @description@ Picks博士观察完金星凌日后,设计了一个复杂的电阻器.为了简化 ...