当前位置: 首页 > news >正文

鸿蒙实战开发:【分布式软总线组件】

简介

现实中多设备间通信方式多种多样(WIFI、蓝牙等),不同的通信方式使用差异大,导致通信问题多;同时还面临设备间通信链路的融合共享和冲突无法处理等挑战。分布式软总线实现近场设备间统一的分布式通信管理能力,提供不区分链路的设备间发现连接、组网和传输能力,主要功能如下:

  • 发现连接:提供基于Wifi、蓝牙等通信方式的设备发现连接能力。
  • 设备组网:提供统一的设备组网和拓扑管理能力,为数据传输提供已组网设备信息。
  • 数据传输:提供数据传输通道,支持消息、字节、流、文件的数据传输能力。

业务方通过使用分布式软总线提供的API实现设备间的高速通信,不用关心通信细节,进而实现业务平台的高效部署与运行能力。

系统架构


图 1 分布式软总线组件架构图

约束

  • 组网设备需在同一局域网中 或者 距离相近的近场设备间。
  • 组网之前,需先完成设备绑定,绑定流程参见安全子系统中说明。
  • 传输完成数据收发之后,业务要主动关闭会话,释放资源。

说明

使用说明

须知: 使用跨设备通信时,必须添加权限ohos.permission.DISTRIBUTED_DATASYNCohos.permission.DISTRIBUTED_SOFTBUS_CENTER,该权限类型为 dangerous

设备主动发现手机时,手机需打开超级终端的允许被“附近设备”发现开关(设置-超级终端-我的设备-允许被发现-附近设备),才能被设备发现。

1、发现

  • 发布流程
  1. 上层应用需要对外发布自身能力时,调用服务发布接口发布自身能力。

    // 发布回调
    typedef struct {/** Callback for publish result */void (*OnPublishResult)(int publishId, PublishResult reason);
    } IPublishCb;// 发布服务
    int32_t PublishLNN(const char *pkgName, const PublishInfo *info, const IPublishCb *cb);
    
  2. 上层应用不再需要对外发布自身能力时,调用StopPublishLNN接口注销服务。

    // 注销服务
    int32_t StopPublishLNN(const char *pkgName, int32_t publishId);
    
  • 发现流程
  1. 上层应用需要发现特定能力设备时,调用发现接口启动发现。

    // 发现回调
    typedef struct {/** Callback that is invoked when a device is found */void (*OnDeviceFound)(const DeviceInfo *device);/** Callback for a subscription result */void (*OnDiscoverResult)(int32_t refreshId, RefreshResult reason);
    } IRefreshCallback;// 发现服务
    int32_t RefreshLNN(const char *pkgName, const SubscribeInfo *info, const IRefreshCallback *cb);
    
  2. 当软总线发现到设备时,通过回调接口通知业务所发现的设备信息。

  3. 上层应用不再需要发现时,调用StopRefreshLNN接口停止设备发现。

    // 停止发现
    int32_t StopRefreshLNN(const char *pkgName, int32_t refreshId);
    

2、组网

  1. 发起组网请求,携带组网连接地址信息,并且提供组网执行结果回调函数。

    // 组网连接地址
    typedef struct {ConnectionAddrType type;union {struct BrAddr {char brMac[BT_MAC_LEN];} br;struct BleAddr {char bleMac[BT_MAC_LEN];uint8_t udidHash[UDID_HASH_LEN];} ble;struct IpAddr {char ip[IP_STR_MAX_LEN];uint16_t port; } ip;} info;char peerUid[MAX_ACCOUNT_HASH_LEN];
    } ConnectionAddr;// 组网连接地址类型
    typedef enum {CONNECTION_ADDR_WLAN = 0,CONNECTION_ADDR_BR,CONNECTION_ADDR_BLE,CONNECTION_ADDR_ETH,CONNECTION_ADDR_MAX
    } ConnectionAddrType;// 组网请求执行结果回调
    typedef void (*OnJoinLNNResult)(ConnectionAddr *addr, const char *networkId, int32_t retCode);// 发起组网请求
    int32_t JoinLNN(const char *pkgName, ConnectionAddr *target, OnJoinLNNResult cb);
    
  2. 等待组网结果,JoinLNN()返回成功表示软总线接受了组网请求,组网结果通过回调函数通知业务;组网回调函数中addr参数内容和JoinLNN()的入参互相匹配;retCode如果为0,表示组网成功,此时networkId为有效值,后续传输、退网等接口均需使用该参数;retCode如果不为0,表示组网失败,此时networkId为无效值。

  3. 使用传输相关接口进行数据传输。

  4. 发送退网请求,携带组网成功后返回的networkId,并且提供退网执行结果回调。

    // 退网执行结果回调
    typedef void (*OnLeaveLNNResult)(const char *networkId, int32_t retCode);// 退网请求
    int32_t LeaveLNN(const char *pkgName, const char *networkId, OnLeaveLNNResult cb);
    
  5. 等待退网完成,OnLeaveLNNResult()的networkId和退网请求接口中的networkId互相匹配;retCode为0表示退网成功,否则退网失败。退网成功后,networkId变为无效值,后续不应该被继续使用。

  6. 使用节点(即设备)注册和注销接口,监听网络中节点状态变化等事件。

    // 事件掩码
    #define EVENT_NODE_STATE_ONLINE 0x1
    #define EVENT_NODE_STATE_OFFLINE 0x02
    #define EVENT_NODE_STATE_INFO_CHANGED 0x04
    #define EVENT_NODE_STATUS_CHANGED 0x08
    #define EVENT_NODE_STATE_MASK 0xF// 节点信息
    typedef struct {char networkId[NETWORK_ID_BUF_LEN];char deviceName[DEVICE_NAME_BUF_LEN];uint16_t deviceTypeId;
    } NodeBasicInfo;// 节点状态事件回调
    typedef struct {uint32_t events; // 组网事件掩码void (*onNodeOnline)(NodeBasicInfo *info);   // 节点上线事件回调void (*onNodeOffline)(NodeBasicInfo *info);  // 节点下线事件回调void (*onNodeBasicInfoChanged)(NodeBasicInfoType type, NodeBasicInfo *info); // 节点信息变化事件回调void (*onNodeStatusChanged)(NodeStatusType type, NodeStatus *status); // 设备运行状态变化事件回调
    } INodeStateCb;//  注册节点状态事件回调
    int32_t RegNodeDeviceStateCb(const char *pkgName, INodeStateCb *callback);// 注销节点状态事件回调
    int32_t UnregNodeDeviceStateCb(INodeStateCb *callback);
    

3、传输

  1. 创建Socket。

    typedef struct {char *name;                 // 本端Socket名称char *peerName;             // 对端Socket名称char *peerNetworkId;        // 对端Socket的网络IDchar *pkgName;              // 调用者包名TransDataType dataType;     // 传输的数据类型,需要与发送方法一致
    } SocketInfo;// 创建Socket
    int32_t Socket(SocketInfo info);
    
  2. 服务端启动监听,客户端进行绑定。

    // Socket回调函数
    typedef struct {void (*OnBind)(int32_t socket, PeerSocketInfo info);void (*OnShutdown)(int32_t socket, ShutdownReason reason);void (*OnBytes)(int32_t socket, const void *data, uint32_t dataLen);void (*OnMessage)(int32_t socket, const void *data, uint32_t dataLen);void (*OnStream)(int32_t socket, const StreamData *data, const StreamData *ext, const StreamFrameInfo *param);void (*OnFile)(int32_t socket, FileEvent *event);void (*OnQos)(int32_t socket, QoSEvent eventId, const QosTV *qos, uint32_t qosCount);
    } ISocketListener;typedef enum {QOS_TYPE_MIN_BW,            // 最小带宽QOS_TYPE_MAX_LATENCY,       // 最大建链时延QOS_TYPE_MIN_LATENCY,       // 最小建链时延QOS_TYPE_MAX_WAIT_TIMEOUT,  // 最大超时时间QOS_TYPE_MAX_BUFFER,        // 最大缓存QOS_TYPE_FIRST_PACKAGE,     // 首包大小QOS_TYPE_MAX_IDLE_TIMEOUT,  // 最大空闲时间QOS_TYPE_TRANS_RELIABILITY, // 传输可靠性QOS_TYPE_BUTT,
    } QosType;typedef struct {QosType qos;int32_t value;
    } QosTV;// 监听Socket,由服务端开启。
    int32_t Listen(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener);// 绑定Socket,由客户端开启。
    int32_t Bind(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener);
    
  3. 通过Socket向对端设备发送数据。

    // 发送字节数据
    int32_t SendBytes(int32_t socket, const void *data, uint32_t len);
    // 发送消息数据
    int32_t SendMessage(int32_t socket, const void *data, uint32_t len);
    // 发送流数据
    int32_t SendStream(int32_t socket, const StreamData *data, const StreamData *ext, const StreamFrameInfo *param);
    // 发送文件
    int32_t SendFile(int32_t socket, const char *sFileList[], const char *dFileList[], uint32_t fileCnt);
    
  4. 关闭Socket。

    // 关闭Socket
    void Shutdown(int32_t socket);
    

    鸿蒙OpenHarmony知识已更新←前往

7ebde29c85a3faa0ae369e2ea9dd3130.jpeg

相关文章:

  • 电源ATE自动测试系统为您提供一站式自动化测试解决方案
  • 有趣之matlab-烟花
  • Element-Plus: Select组件实现滚动分页加载
  • Python笔记|字符串的转义
  • 09-设计模式 企业场景 面试题
  • PTA L1-079 天梯赛的善良(C++)
  • MySQL一些命令记录
  • R在直方图上添加一个更平滑的密度曲线
  • PCM和I2S区别
  • 实现真正的高性能高并发的上亿级别秒杀系统!!!
  • 姿态旋转的哥氏定理以及速度微分的推导
  • 蓝桥杯---棋盘(典型的二维差分问题)
  • 利用 Python 处理遥感影像数据:计算年度平均影像
  • Word中解决插入脚注导致的分页位置错误问题
  • 【消息队列开发】 实现内存加载
  • 《Java编程思想》读书笔记-对象导论
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • JAVA_NIO系列——Channel和Buffer详解
  • js对象的深浅拷贝
  • overflow: hidden IE7无效
  • PermissionScope Swift4 兼容问题
  • spring boot 整合mybatis 无法输出sql的问题
  • Spring Boot快速入门(一):Hello Spring Boot
  • Swift 中的尾递归和蹦床
  • ubuntu 下nginx安装 并支持https协议
  • 程序员最讨厌的9句话,你可有补充?
  • 搭建gitbook 和 访问权限认证
  • 机器学习 vs. 深度学习
  • 基于游标的分页接口实现
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 使用common-codec进行md5加密
  • 我有几个粽子,和一个故事
  • 一天一个设计模式之JS实现——适配器模式
  • 用jquery写贪吃蛇
  • No resource identifier found for attribute,RxJava之zip操作符
  • Java数据解析之JSON
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • postgresql行列转换函数
  • 浅谈sql中的in与not in,exists与not exists的区别
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​iOS安全加固方法及实现
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • #14vue3生成表单并跳转到外部地址的方式
  • #define、const、typedef的差别
  • (4)(4.6) Triducer
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (学习日记)2024.01.19
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • *ST京蓝入股力合节能 着力绿色智慧城市服务