libdbus 实例以及使用d-feet查看接口方法

libdbus介绍

总线

​ linux系统进程间通过dbus通信,D-BUS由总线构成,总线分为两种,系统总线(system-bus)和会话总线(session-bus)。系统总线在引导时就会启动,这个总线由操作系统和后台进程使用,安全性非常好,以使得任意的应用程序不能欺骗系统事件.会话总线在用户登陆后启动,属于用户私有,是用户进程用来通信的一个会话总线。如果一个应用程序需要接收来自系统总线的消息,可以直接连接到系统总线 —— 不过,它可以发送的消息将是受限的。只有Linux内核、Linux桌面环境和权限较高的程序才能向系统总线写入消息,以此保障系统安全性,防止有恶意进程假冒Linux发送消息。

服务名

​ 每个应用程序连接到总线后,指定一个服务名,bus name;

对象名

​ 消息发送到指定的对象,对象格式类似路径名称:/com/jimi/dbus

接口名

​ 一组功能的集合名字,com.jimi.test,接口下实现很多方法或者信号

消息类型

​ 在 D-BUS 中有四种类型的消息:方法调用(method calls)、方法返回(method returns)、信号(signals)和错误(errors)。要执行 D-BUS 对象的方法,您需要向对象发送一个方法调用消息。它将完成一些处理(就是执行了对象中的Method,Method是可以带有输入参数的。)并返回,返回消息或者错误消息。信号的不同之处在于它们不返回任何内容:既没有“信号返回”消息,也没有任何类型的错误消息

signal

​ 发送信号,接收者获取信号,并响应信号的事件,信号不返回数据。

method

​ 客户端调用服务端的方法,有输入,有输出。

当一个应用连接到bus daemon,daemon立即会分配一个名字给这个连接,称为unique connection name ,这个唯一标识的名字以冒号:开头,例如:34-907,这个名字在daemon的整个生命周期是唯一的。但是这种名字总是临时分配,无法确定的,也难以记忆,因此应用可以要求有另外一个名字well-known name 来对应这个唯一标识,就像我们使用域名来对应IP地址一样。例如可以使用com.mycompany来映射:34-907。

Address –> [BusName] –> Path –> Interface –> Method

bus name不是必要的,它只在daemon的情况下用于路由,点对点的直接连接是不需要的。

​ 简单地说:Address是D-Bus中server用来监听client的地址,当一个client连接上D-Bus,通常是Daemo的方式,这个client就有了一个Bus Name。其他应用可以根据消息中所带的Bus Name,来判断和哪个应用相关。消息在总线中传递的时候,传递到应用中,再根据objectpath,送至应用中具体的对象实例中,也就是是应用中根据Interface创建的对象。这些Interface有method和singal两种,用来发送、接收、响应消息。

消息通过D-Bus在进程间传递。有四类消息:

一、Method call消息:将触发对象的一个method

二、Method return消息:触发的方法返回的结果

三、Error消息:触发的方法返回一个异常

四、Signal消息:通知,可以看作为事件消息。

libdbus 服务端demo

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdlib.h>
#include <dbus/dbus.h>
#include <unistd.h>using namespace  std;
using json = nlohmann::json;
static DBusConnection *connect;const char * object_path = "/com/jimi/dbus";
const char * signal_object_path = "/signal/jimi/dbus";
const char * method_interface = "ipc.method";
const char * signal_interface = "ipc.signal";
void handle_unregister(DBusConnection * connection, void * user_data);
DBusHandlerResult message_handler(DBusConnection * connection,DBusMessage * msg,void * user_data);
int dbus_send_signal(DBusConnection * connection,const char *signalName, char *value);static DBusObjectPathVTable server_path_vt = {.unregister_function = handle_unregister,.message_function = message_handler
};typedef struct {dbus_uint32_t id;
}ConnectData;ConnectData server_data = {0};void reply_to_method_call(DBusMessage * msg, DBusConnection * conn){DBusMessage * reply;DBusMessageIter arg;char * param = NULL;dbus_bool_t stat = TRUE;dbus_uint32_t level = 2010;dbus_uint32_t serial = 0;//从msg中读取参数,这个在上一次学习中学过if(!dbus_message_iter_init(msg,&arg))printf("Message has no args/n");else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)printf("Arg is not string!/n");elsedbus_message_iter_get_basic(&arg,&param);printf("%s",param);if(param == NULL) return;string str_reply = param;//创建返回消息replyreply = dbus_message_new_method_return(msg);//在返回消息中填入两个参数,和信号加入参数的方式是一样的。这次我们将加入两个参数。dbus_message_iter_init_append(reply,&arg);if(!dbus_message_iter_append_basic (&arg,DBUS_TYPE_BOOLEAN,&stat)){printf("Out of Memory!/n");exit(1);}if(!dbus_message_iter_append_basic (&arg,DBUS_TYPE_UINT32,&level)){printf("Out of Memory!/n");exit(1);}if(!dbus_message_iter_append_basic (&arg,DBUS_TYPE_STRING,&str_reply)){printf("Out of Memory!/n");exit(1);}//发送返回消息if( !dbus_connection_send (conn, reply, &serial)){printf("Out of Memory/n");exit(1);}dbus_connection_flush (conn);dbus_message_unref (reply);
}void reply_to_introspec(DBusMessage * msg, DBusConnection * conn){DBusMessage * reply;DBusMessageIter arg;dbus_uint32_t serial = 0;string str_reply;//读取xml,xml写入了path下的所有接口及方法,d-feet可以查询ifstream in("/home/uos/dbus_test.xml");stringstream buffer;buffer<<in.rdbuf();str_reply = buffer.str();printf("%s",str_reply.c_str());//创建返回消息replyreply = dbus_message_new_method_return(msg);dbus_message_iter_init_append(reply,&arg);if(!dbus_message_iter_append_basic (&arg,DBUS_TYPE_STRING,&str_reply)){printf("Out of Memory!/n");exit(1);}//发送返回消息if( !dbus_connection_send (conn, reply, &serial)){printf("Out of Memory/n");exit(1);}dbus_connection_flush (conn);dbus_message_unref (reply);
}DBusHandlerResult message_handler(DBusConnection * connection,DBusMessage * msg,void * user_data)
{DBusMessageIter arg;char * sigvalue;if(!msg){return DBUS_HANDLER_RESULT_HANDLED;}switch(dbus_message_get_type(msg)){case DBUS_MESSAGE_TYPE_METHOD_CALL:{if(dbus_message_is_method_call(msg,method_interface,"test_method")){auto path = dbus_message_get_path (msg);if(strcmp(path,object_path) == 0){reply_to_method_call(msg, connection);}}else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE,"Introspect")){ //"org.freedesktop.DBus.Introspectable"auto path = dbus_message_get_path (msg);if(strcmp(path,object_path) == 0){reply_to_introspec(msg, connection);}}break;}case DBUS_MESSAGE_TYPE_SIGNAL:{if(dbus_message_is_signal(msg, signal_interface, "test_signal")){if(!dbus_message_iter_init(msg,&arg))fprintf(stderr,"Message Has no Param");else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)fprintf(stderr,"Param is not string");else{dbus_message_iter_get_basic(&arg,&sigvalue);//信号内容printf("get signal content is : %s",sigvalue);fflush(stdout);//dbus_send_signal(connection, "test_signal", sigvalue);reply_to_method_call(msg, connection);}}break;}case DBUS_MESSAGE_TYPE_METHOD_RETURN:{return DBUS_HANDLER_RESULT_HANDLED;}case DBUS_MESSAGE_TYPE_INVALID:{return DBUS_HANDLER_RESULT_HANDLED;}default:return DBUS_HANDLER_RESULT_HANDLED;}}void handle_unregister(DBusConnection * connection, void * user_data){dbus_free(user_data);
}void dbus_server()
{DBusMessage * msg;DBusMessageIter arg;DBusConnection * connection;DBusError err;int ret;char * sigvalue;dbus_error_init(&err);//创建于session D-Bus的连接connection = dbus_bus_get(DBUS_BUS_SESSION, &err);if(dbus_error_is_set(&err)){fprintf(stderr,"Connection Error %s/n",err.message);dbus_error_free(&err);}if(connection == NULL)return;//设置一个BUS name:test.wei.destret = dbus_bus_request_name(connection,"com.jimi.dbus",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);if(dbus_error_is_set(&err)){fprintf(stderr,"Name Error %s/n",err.message);dbus_error_free(&err);}if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)return;ret = dbus_connection_register_object_path(connection,object_path,&server_path_vt,&server_data);if(dbus_error_is_set(&err)){fprintf(stderr,"Name Error %s/n",err.message);dbus_error_free(&err);}//消息循环while(dbus_connection_read_write_dispatch(connection,-1)){}}
int main(){dbus_server();return 0;
}

以上是一个完整的dbus服务器示例,可以通过d-feet查看接口方法,如果你写的dbus程序在d-feet下看不到对象路径,功能方法调用正常,则是因为没有实现总线的标准接口 org.freedesktop.DBus.Introspectable 的方法Introspect,具体实现如上述代码,introspect方法返回的是xml数据,xml数据定义了接口-方法-参数-类型-入\出方向,d-feet能够显示dbus-server的接口方法,是因为调用了标准接口的Instrospect回显了所有的方法和信号。

dbus_test.xml内容定义如下:

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN""http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"><node><interface name="ipc.signal"><signal name="test_signal"><arg name="info" type="s" direction="out"/></signal></interface><interface name="ipc.method"><method name="test_method"><arg name="input" type="s" direction="in"/></method></interface><interface name="org.freedesktop.DBus.Introspectable"><method name="Introspect"><arg name="xml_data" type="s" direction="out"/></method></interface><interface name="org.freedesktop.DBus.Properties"><method name="Get"><arg name="interface" type="s" direction="in"/><arg name="propname" type="s" direction="in"/><arg name="value" type="s" direction="out"/></method><method name="Set"><arg name="interface" type="s" direction="in"/><arg name="propname" type="s" direction="in"/><arg name="value" type="s" direction="in"/></method><method name="GetAll"><arg name="interface" type="s" direction="in"/><arg name="props" type="a{sv}" direction="out"/></method></interface></node>

dbus-send 用法

Usage: dbus-send [--help] [--system | --session | --bus=ADDRESS | --peer=ADDRESS] [--dest=NAME] [--type=TYPE] [--print-reply[=literal]] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]

–system root用户进程dbus

–session 用户进程dbus
–print-reply 打印输出

–type=method_call / signal

–dest 目的服务名 方法路径 接口+method 参数类型:参数值

方法测试

信号测试

libdbus 实例以及使用d-feet查看接口方法相关推荐

  1. 从Linux上查看接口路由IP(吓一跳ip)

    #traceroute 172.17.10.27 //查看接口地址吓一跳路由IP

  2. 微信开发者工具-真机调试,可查看接口信息

    之前测试小程序查看接口信息,是需要打开调试模式,手机界面小,看着多多少少有点不方便. 现在发现了可以直接找前端要文件包,用[微信开发者工具]打开该文件包,然后选择[真机调试]-[二维码真机调试],生产 ...

  3. fn+f12查看接口

    fn+f12  开发者工具 1.查看接口 (例如:cms登录接口) url:http://cms.duoceshi.cn/cms/manage/index.do 2.按fn+12 3.找到接口后,在分 ...

  4. IDEA查看接口的实现类 快捷键

    Ctrl + B 快速打开光标处的类或方法 Ctrl + Alt + B 查看接口的实现类 Ctrl + Shift + B 跳转到类型声明处

  5. Postman系列(七)-查看接口响应

    Postman 响应查看器可以用来查看接口响应.接口响应由正文.标头和状态代码组成.Postman 在不同的选项卡中展示body和header.接口调用的状态代码和完成时间显示在选项卡旁边. 1.保存 ...

  6. linux防火墙查看方法有,linux防火墙状态查看的方法实例

    linux防火墙状态查看的方法 1.基本操作 # 查看防火墙状态 service iptables status # 停止防火墙 service iptables stop # 启动防火墙 servi ...

  7. 接口响应时间长排查,通过nginx日志查看接口响应时间

    场景 vue项目中,页面请求接口响应速度非常慢,F12打开谷歌控制台,查看network,发现响应时间为1.14秒 排查问题 接口响应速度慢,后端打断点进入接口到返回这段时间有很快,要判断是什么问题, ...

  8. Fiddler抓包查看接口的响应时间

    一.Fiddler抓包查看接口的响应时间 1.需要在每个接口后面直观查看响应时间,不用看右侧Statistics查看Overall Elapsed响应时间 上网百度的资料 2.在右侧FiddlerSc ...

  9. linux 防火墙查看出错,linux防火墙状态查看的方法实例

    linux防火墙状态查看的方法 1.基本操作 # 查看防火墙状态 service iptables status # 停止防火墙 service iptables stop # 启动防火墙 servi ...

  10. 浏览器F12查看接口信息

    1.首先F12打开控制台,点击Network,再点击XHR,就可以查看接口名和接口相关信息

最新文章

  1. php的内存划分,解析PHP中的内存管理,PHP动态分配和释放内存
  2. php5.2通过saprfc扩展远程连接sap730成功案例
  3. AAAI2020录用论文汇总(三)
  4. linux 建议锁和强制锁
  5. ashx获取input file 文件_前端战五渣学前端——FileReader预览本地文件
  6. php+nginx环境下的php报错设置
  7. 运筹优化(十二)--带约束非线性规划(NLP)
  8. Python处理多种编码报错的处理
  9. python psutil模块怎么在线下载_python之psutil模块
  10. 惠普m1216硒鼓清零步骤_显示耗材余量错误怎么解决呢,一招搞定
  11. 如何卸载Adobe Premiere Pro CC 2017和Adobe Photoshop CC 2018
  12. 腾讯QQ、新浪微博第三方登录接口申请说明
  13. 微信“小程序”要来了,简单点,解释的方式简单点
  14. VC/MFC 使用jsoncpp解析json格式内容
  15. dell服务器设置bios设置u盘启动不了系统,戴尔台式机bios设置图解教程|dell bios设置u盘启动...
  16. 华为防火墙的NAT介绍及配置详解
  17. 被带走的机密文件WP
  18. centos7 gitlab14搭建完成后,无法访问的问题处理(“error“:“badgateway: failed to receive response: dial unix /var/opt)
  19. PLASTIGAUGE塑料间隙规的正确使用步骤你知道多少?
  20. html5怎么设置滚动字幕,HTML5如何设置滚动字幕?_惠州网页设计

热门文章

  1. 分享Silverlight/WPF/Windows Phone一周学习导读(07月11日-07月17日)
  2. Flutter Sliver滚动组件
  3. python 判断每月最后一天_在Python中获取本月的最后一天
  4. java中如何表达sin_在Java中使用“sincos”
  5. Java 微信二维码支付
  6. 美国人口的模型预测——非线性最小二乘法
  7. [NIPS 2018] Delta Encoder: An Effective Sample Synthesis Method for Few Shot Object Recognition
  8. 各种浏览器兼容性报告大全
  9. 【NLP】自然语言处理中常见的英文单词
  10. Segmentation Fault错误原因总结