简介
这里无网通信指的是没有互联网的通信方式,之前在区块链公司是做这块,现在怕自己以后忘了写一遍,之前搞工业机器人实在太忙,整个博客停了,也不搞移动了,现在离职了,创业也败了,该恢复一下之前的技术调整心态继续找工作了。
所谓无网通信其实是不同设备互相发现然后连接进行通信,而互相发现的方式可以归纳成三种
- 两个设备连接在同一个WIFI
- 两个设备通过WLAN创建点对点连接
- 两个设备通过蓝牙BLE创建点对点连接
而前两种是最稳定的方式,可以使用Wifi Direct实现,而蓝牙BLE的方式就比较鸡肋了距离有限制大小也有限制,能Wifi直连肯定不用蓝牙。然而蓝牙的发现连接标准其实各个设备基本都遵循的是一套,但Wifi Direct则是实现方式多种多样像UPnP、Bonjour、DLNA、SLP抑或是其他技术都能实现。iOS用的自家Bonjour,而Android4.0后开始支持直接就叫Wifi Direct,不同设备直连基本都会遇到问题。这里以Android和iOS为例实现的基本逻辑其实都由MDNS与DNS-SD演化而来。
确定了Wifi Direct以后又会发现一个问题就是这解决的是设备与设备的通信,也就是一对一,而理想的无网通信是多对多,信息流之间希望有多跳的能力也就是Mesh,这个最终我们也没完美解决,虽然Android和iOS里有一定的解决方案(创建群组实现多对多)但也有不同系统无法互通的问题和群组上限问题,但当时我们选择了更简单的方式就是由路由器去Mesh其他路由器,而设备加入到路由器的网络里直接用MDNS去发现然后链接通信,专业设备做专业事,Mesh组网和设备通信分摊到两个地方。
MDNS(Multicast DNS)与DNS-SD(DNS Service Discovery)
简介里介绍完基本就确定了技术点就是Wifi Direct,而这项技术则是由MDNS(Multicast DNS)与DNS-SD(DNS Service Discovery)演化而来。
首先MDNS和DNS-SD是DNS协议的两个扩展。MDNS扩展了域名服务系统,在链路本地多播上运行。DNS-SD添加了通过DNS发现网络服务的支持。MDNS原理就是在基于udp加入网络后向所有主机组播一个消息。
基本流程就是基于某个自定义域名发布服务,发现设备,连接设备
Andoid
安卓官网写的很详细非常友好
独立设备下Andoid NSD
这里讲的是不加入到任何共同网络中的独立设备,通过android的Wifi Direct实现启动服务发现设备而且是有条件的发现,类似MDNS可以指定启动及发现服务的名称
在同一网络下Andoid NSD
这里讲的是在设备加入到同一网络中发现设备,而这块则是最标准最通用的,遵循MDNS协议实现设备的发现解析出host,我们当时就是运用这个使得Android,iOS,其他设备都能在网络下互相发现我们的服务,其他设备用Golang的MDNS,github能搜到很多封装好的,而且区块链著名的二层网络Rainden Network的节点发现也有用到它。像智能设备的控制基本都可以选择这个方案解决
Andoid WIFI直连
这里主要讲的是第一个类似,但他是无差别的去发现附近开启对等连接的设备,然后还讲了分组和连接有点对标iOS MutipeerConnectivity的意思。
iOS
首先苹果官网想通过关键词搜索相关技术你没看过WWDC基本上搜不出来,尤其是近几年的东西你就算搜出来,越是抽象的API越是没啥注释,越是看注释就知道怎么用的,它还给你来个示例代码。下面开始详细说说:
iOS主要提供了3个方式MutipeerConnectivity,Network库,NSNetService相关,而我当时用的是NSNetService因为那个时候还没有Network库,现在这些类都已经被淘汰了,而MutipeerConnectivity虽然方法封装的更好用而且同时支持蓝牙和wifi直连,但你没法控制代码去控制用哪个,而且由于太标准无法做和android的通信,但如果是仅仅iOS间通信聊天,却能直接轻松实现群组间的聊天。
MutipeerConnectivity
这示例代码实现了无网聊天在不加入网络的情况下发现附近的群组加入进行聊天,但是直接看代码还是有点费劲不向上面Android的文档讲了关键的几个方法,所以我就依照示例和常用的挑出核心代码简单讲一下。
1 | //创建一个设备ID |
1 | @try { |
1 | #pragma mark - MCNearbyServiceAdvertiserDelegate |
1 | // 开启广播 |
1 | //创建回话对象,用于存放当前连接的会话 |
1 | //停止广播 |
1 | //发送消息给当前会话中的对象 |
1 | NSProgress *progress; |
1 | #pragma mark - MCSessionDelegate |
1 | //创建搜索蓝牙设备控制器 |
1 | #pragma mark - MCBrowserViewControllerDelegate |
上面就是实现聊天功能的一些代码片段,但反过来想一下,这个功能主要是实现发现附近设备加入聊天室聊天,这场景其实比较奇怪,离得不远的话聊两句破冰了肯定流传了毕竟离得不远直接面对面不是更好,只有在游戏场景里这种近点通信才是一个比较好的交流方式,比如游戏道具的互换,游戏竞技比赛这类场景跟这类技术才会比较搭配,聊天的话真的就当个例子就好。。。
NSNetService
这里示例代码实现的是使用NSNetService实现两个设备连接后点击色块反馈,现在这个类已经被弃用代替方法是Network库。
这里简单简绍就不已经示例代码了,因为这块可以直接实现和安卓的互通所以就以我个人总结的几个关键地方为主。
安卓方面使用就是 在同一网络下Andoid NSD 叙述的设置
1 | //初始化广播服务为了和Android通信Domain为空字符串,其他的Android上都有,至于port就是你起服务的Socket端口 |
1 | #pragma mark - Bonjour |
1 | //设置委托 |
1 | #pragma mark - NSNetServiceDelegate |
1 | //启动发现服务,之前测试停掉再启动就不生效了,所以每次都重新初始化 |
通过上面代码就能实现iOS和Android发现彼此设备的IP和端口,只要你起好tcp的server就能进行连接通信,至于起server随便百度一下就有很多socket起服务的方法这里就不做赘述了我是直接用CocoaAsyncSocket,我当时为了保险做成了混合式发现入网后还会定期udp广播一下其实没必要。
Network库
这个没在官方找到什么好的示例代码所以直接就给出了官方文档,在网上看到过不少散装的,NSNetService对应NWConnection初始化用NWEndpoint来初始化,NSNetServiceBrowser对应NWBrowser
1 | import Network |
1 | //初始化tcp server,入参对应NSNetService初始化的 |
1 | //初始化tcp client |
新的Network库好处是直接把socket和注册广播服务整合了,这个也没真正测过在这里只是做个记录。