前言
终于写到了flutter初体验的最后一篇,一直想等应用上架了再把这一篇发出来,结果到现在拖了快一个月了。
这里先给没看过前几篇的朋友讲下前情提要:前段时间,我学了一下谷歌的跨平台客户端框架flutter,并用它搭建了一个网络设备扫描的app,这几篇文章主要是介绍我使用flutter的初体验。
在上一篇里,我介绍了项目中ui端的一些要点,有兴趣的朋友可以先看看上一篇:我的Flutter初体验-2-ui端优快云/酷安。
在之前的文章中,根据app的工作流程,我将逻辑端分为多个模块,本篇文章就介绍一下每个模块的实现方式和要点。
逻辑端
根据app功能和工作流程,可以将逻辑端分为以下模块:
- 设备扫描模块
- mac查询模块
- 厂商查询模块
下面针对不同模块进行详细介绍。
设备扫描模块
设备扫描模块的功能是从一个ip范围之内找到所有可达的ip地址,其工作流程大致分为几步:
- 输入ip范围,将ip范围解析为单个ip地址
- 判断每个ip地址是否可达
- 异步返回扫描结果
第一步比较简单,就不再描述了,下面主要介绍一下后两步。
大家都知道,判断ip地址是否可达有很多种方法,ping是一个比较简单且常用的方法。想要使用dart语言ping一个ip地址,主要有下面几个手段:
- 采用icmp协议手动发送ping报文
- 构建报文
- 发送报文
- 解析报文
- 调用系统ping命令,并解析命令执行结果
- 通过
dart:io
包中的Process类执行命令 - 正则表达式解析返回结果
- 通过
- 采用第三方库
- dart_ping
- flutter_icmp_ping
- …
上述几种手段中:
- 手动构建icmp协议比较复杂(细节较多,且由于icmp是网络层协议,需要提权),所以不在我的考虑范围内(太菜了);
- 调用系统ping命令较为简单,但是需要注意中文windows采用的是gbk编码,因此在获取命令执行结果时,需要显示定义gbk编解码器;
- 采用第三方库是最简单,但很多库对不同平台的支持有限。我看了下这些库的源码,它们实际也都是通过调用系统命令实现ping的(殊途同归了属于是)。
在项目里,对于windows平台,我采用了调用系统ping命令的方法(编解码原因),对于其他平台,我采用了第三方库ping操作(简单方便)。
扫描结果的异步返回,既可以使用Future,也可以使用Stream,我在项目中采用了Stream来实现。
mac查询模块
在数据链路层中,需要区分不同主机,以确定数据帧传输的目的地,mac地址正是用来区分主机的标识。mac地址共6个字节48位,前24位是ieee分配的厂商标志,后24位是厂商分配的设备标志。
在windows中,可以通过ipconfig
命令查看自身mac地址;在linux中可以通过ifconfig
或ip addr
查看自身mac地址。而想要获取其他设备的mac地址,可以通过读取arp缓存来实现。
arp协议是一个通过ip地址获取网络设备mac地址的协议,在每次广播arp请求并受到响应后,设备会将收到的ip和mac地址存入本机的arp缓存中,并保留一段时间。所以,通过读取arp缓存,我们就能通过ip地址查询到该地址对应设备的mac地址,虽然可能会出现错误(设备ip地址发生变化),但大致上还是可靠的。
在不同的平台上读取arp缓存的方法不同:
- windows:
- 执行
arp -a
命令
- 执行
- linux
- 执行
arp -a
命令 - 执行
ip neigh
命令 - 读取
/proc/net/arp
文件
- 执行
- android
- 执行
ip neigh
命令
- 执行
通过上述几种方法读取arp缓存后,采用正则表达式解析出ip和mac地址的对应关系,就可以通过第一步扫描到ip地址查询到该设备的mac地址。
之前好像还没有人写过dart读取arp缓存的包,所以我抽取了这部分功能并发布了出来,可以去dart packages里面搜arp_cache_loader。
厂商查询模块
上面讲到mac地址中前24位是由ieee分配给厂商的,这部分被称为oui(organization unique identifier),那么我们理所当然的可以通过mac地址查询到设备所属的厂商。通过mac地址查询厂商有下面几种方法:
- 通过ieee官方文件查询
- 官方文件出现在ieee的oui官网上:
- https://standards-oui.ieee.org/oui/oui.txt
- 通过第三方搭建的网站查询
- 国内:
- https://mac.51240.com/
- 国外:
- https://macvendors.com/
- https://www.macvendorlookup.com
- https://www.wireshark.org/tools/oui-lookup.html
- https://aruljohn.com/mac.pl
- 国内:
我在项目中采用了第三方网站:macvendors.com,这个网站提供了方便的api接口,虽然免费账户限制每秒最多2次查询,但是只要加上重试机制,那么次数限制就不是问题~
总结
这次开发总体来说比较顺利,在前期学习flutter和dart的过程中也没遇到太大的麻烦。这次的开发不仅让我了解了一些客户端搭建方面的知识,也巩固和加强了我计算机网络、项目结构、异步操作等方面的知识和能力,可谓收获良多。
根据个人体验,我总结了几条flutter的优缺点:
- 优点:
- 跨平台(最重要的一点)
- 简单易学(工具完善、dart语法简单)
- 代码统一(ui和逻辑均为dart语言)
- 高效(开发时采用jit)
- 高性能(接近原生的体验)
- 较为完善的支持(谷歌背书、开发者社区)
- 缺点:
- 国内不太流行(采用flutter的大厂应用较少)
- 底层操作支持不完善(一些操作需要调用原生代码,不同平台需要各自实现)
- 包体积较大(虽然有摇树优化,但flutter引擎仍要占用几到十几MB的容量)
由于底层操作、包体积等问题,我个人认为flutter更适合用来构建服务类应用,而不太适合构建系统工具类应用(flutter本身也提供了许多好看的ui效果,不用来搭建服务类应用就可惜了)。
以上均是我个人观点,有不同意见的朋友可以友善交流~
最后附上app和项目地址:
- app地址:酷安/蓝奏云 密码:a5cv
- 项目地址:Device Detector