润小云解读鸿蒙OS系列(五):分布式软总线之discovery_service
discovery_service提供了设备的发布接口。
鸿蒙OS支持的设备
discovery\discovery_service\include\common_info_manager.h中,定义了目前鸿蒙OS支持的设备类型和设备级别,从定义不难看出,目前鸿蒙OS只支持L0和L1的设备。

这里要补充一下,由于L0的设备不支持多线程并且只支持轻量级的TCP/IP协议,因此在涉及多线程和网络通信的代码,多会看到如下的条件编译语句:

上述条件编译表示其中到代码是专门为L0设备提供的。

上述条件编译表示其中代码是专门为L1设备提供。
用户使用发现功能时,需要保证发现端设备与被发现端设备在同一个局域网内,并且互相能收到对方以下流程的报文。
(1)发现端设备,发起discover请求后,使用coap协议在局域网内发送广播。
(2)被发现端设备使用PublishService接口发布服务,接收端收到广播后,发送coap协议单播给发现端。
(3)发现端设备收到报文会更新设备信息。
下面是设备的定义,分为本地设备(被发现端设备)和外部设备,从中不难看出鸿蒙OS的分布式特性,本地设备可以通过PublishService函数将自身的服务发布出去,供外部设备发现并使用。鸿蒙OS的设备发现机制是被发现设备在COAP端口监听来自发现设备的广播包,这也符合按需使用的原则。

PublishService的启动过程
被发现端设备通过调用PublishService向外部发布设备的能力,接口使用示例如下:

我们分2段来看PublishService这个函数。
PublishService首先将检查是否有发布权限以及检查了一些发布参数的合法性,其次确认发布协议是不是COAP。

然后,考虑到被发现端上可能有多个设备对外部发布服务,因此创建了一个信号量g_serviceSemId来防止冲突。进入信号量之后,

主要调用InitService函数来启动服务,并将模块注册到全局变量g_publishModule中,服务注册到g_capabilityData中。

下面我们来看一下服务启动函数InitService,因为InitService可能被多个设备所调用,因此通过全局变量g_isServiceInit来确认服务是否启动,如果其他设备以及启动则直接略过。如果没有,则需要做很多初始化工作。

服务启动函数InitService首先调用InitCommonManager,InitCommonManager再调用InitLocalDeviceInfo初始化本地设备信息。本地设备的信息被保存在g_deviceInfo这个全局变量中。接下来,服务启动函数InitService初始化了两个全局变量,g_publishModule和g_capabilityData,分别用来存放发布的模块和能力描述数据。之后,调用CoapInit函数,CoapInit则会调用NSTACKX_Init,NSTACKX_Init调用CoapInitDiscovery来启动COAP端口监听。CoapInitDiscovery的解析详见润小云解读鸿蒙OS系列(三):分布式软总线之COAP协议。