在 D-BUS 中有四种类型的消息:方法调用(method calls)、方法返回(method returns)、信号(signals)和错误(errors)。
1、使用方法调用实现通信
要执行 D-BUS 对象的方法,您需要向对象发送一个方法调用消息。它将完成一些处理(就是执行了对象中的Method,Method是可以带有输入参数的。)并返回,返回消息或者错误消息
client端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include <dbus/dbus.h>
const char *const INTERFACE_NAME = "in.softprayog.dbus_example";
const char *const SERVER_BUS_NAME = "in.softprayog.add_server";
const char *const CLIENT_BUS_NAME = "in.softprayog.add_client";
const char *const OBJECT_PATH_NAME = "/in/softprayog/adder";
const char *const METHOD_NAME = "test_dbus_damon";
DBusError dbus_error;
void print_dbus_error (char *str);
bool isinteger (char *ptr);
void print_dbus_error (char *str)
{
fprintf (stderr, "%s: %s\n", str, dbus_error.message);
dbus_error_free (&dbus_error);
}
int main(void)
{
DBusConnection *conn = NULL;
DBusMessage *msg = NULL;
//DBusMessageIter args;
DBusPendingCall *pending = NULL;
int ret;
dbus_error_init(&dbus_error);
conn = dbus_bus_get( DBUS_BUS_SYSTEM, &dbus_error);
if( dbus_error_is_set( &dbus_error ) ){
print_dbus_error ("dbus_bus_get");
exit(1);
}
if(NULL == conn){
exit(1);
}
// Get a well known name
#if 0
/****这种方法有可能会停在此处**********/
while (1) {
ret = dbus_bus_request_name (conn, CLIENT_BUS_NAME, 0, &dbus_error);
if (ret == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
break;
if (ret == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) {
fprintf (stderr, "Waiting for the bus ... \n");
sleep (1);
continue;
}
if (dbus_error_is_set (&dbus_error))
print_dbus_error ("dbus_bus_get");
}
/*************************************************/
#endif
#if 1
ret = dbus_bus_request_name(conn, CLIENT_BUS_NAME,DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
if (dbus_error_is_set (&dbus_error))
print_dbus_error ("dbus_bus_get");
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
fprintf (stderr, "Dbus: not primary owner, ret = %d\n", ret);
exit(1);
}
#endif
//创建函数调用
msg = dbus_message_new_method_call(SERVER_BUS_NAME, OBJECT_PATH_NAME, INTERFACE_NAME, METHOD_NAME);
if(msg == NULL){
fprintf (stderr, "Error in dbus_message_new_method_call\n");
exit(1);
}
//开始添加发送数据
char *ptr ="hello";
/******
dbus_message_iter_init_append(msg, &args);
dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &mac, 6, //传递数组
DBUS_TYPE_INT32, &port, DBUS_TYPE_INVALID);
if (!dbus_message_iter_append_args (msg, DBUS_TYPE_STRING, &ptr,DBUS_TYPE_INVALID)) {
dbus_message_unref(msg);//free msg
fprintf (stderr, "Error in dbus_message_iter_append_args\n");
exit(1);
}
****/
DBusMessageIter iter;
dbus_message_iter_init_append(msg, &iter);
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ptr)) {
dbus_message_unref(msg);//free msg
fprintf (stderr, "Error in dbus_message_iter_append_basic\n");
exit (1);
}
if (!dbus_connection_send_with_reply(conn, msg, &pending, -1))
{
dbus_message_unref(msg);
fprintf (stderr,"dbus_connection_send_with_reply failed");
exit(1);
}
if (NULL == pending)
{
dbus_message_unref(msg);
fprintf (stderr,"pending == NULL");
exit(1);
}
//发送数据
dbus_connection_flush(conn);
dbus_message_unref(msg);
dbus_pending_call_block(pending);
//接收返回数据
DBusMessage *reply;
reply= dbus_pending_call_steal_reply(pending);
if (reply== NULL)
{
fprintf (stderr,"call steal reply failed\n");
dbus_message_unref(reply);
exit(1);;
}
dbus_pending_call_unref(pending);
char *s;
//从服务器端返回一个简单的字符串
if (dbus_message_get_args (reply, &dbus_error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) {
printf ("Receive from server: %s\n", s);
}else{
fprintf (stderr, "Did not get arguments in reply\n");
exit (1);
}
dbus_message_unref (reply);
/****************逐个解析获取信息***********
dbus_error_init(&err);
dbus_message_iter_init(msg, &iter);//成功返回1
if(DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&iter)){
dbus_message_iter_get_basic(&iter, &status);//获取DBUS_TYPE_INT32类型数据存放到status
}
dbus_message_iter_next(&iter);//获取下一数据
if(DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&iter)){
dbus_message_iter_get_basic(&iter, &count);
}
//解析获取的数组数据
DBusMessageIter sub_iter;
if(dbus_message_iter_next(&iter){
if(DBUS_TYPE_ARRAY == dbus_message_iter_get_arg_type(&iter)){
dbus_message_iter_recurse(&iter, &sub_iter);
dbus_message_iter_get_fixed_array(&sub_iter, &mac, &mac_len);
}
}
*******************************************/
if (dbus_bus_release_name (conn, CLIENT_BUS_NAME, &dbus_error) == -1) {
fprintf (stderr, "Error in dbus_bus_release_name\n");
exit (1);
}
return 0;
}
server端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <ctype.h>
#include <dbus/dbus.h>
const char *const INTERFACE_NAME = "in.softprayog.dbus_example";
const char *const SERVER_BUS_NAME = "in.softprayog.add_server";
const char *const OBJECT_PATH_NAME = "/in/softprayog/adder";
const char *const METHOD_NAME = "test_dbus_damon";
DBusError dbus_error;
void print_dbus_error (char *str);
static DBusHandlerResult ws_dbus_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data);
int main (int argc, char **argv)
{
DBusConnection *conn;
int ret;
dbus_error_init (&dbus_error);
conn = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
if (dbus_error_is_set (&dbus_error))
print_dbus_error ("dbus_bus_get");
if (!conn)
exit (1);
// Get a well known name
ret = dbus_bus_request_name (conn, SERVER_BUS_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
if (dbus_error_is_set (&dbus_error))
print_dbus_error ("dbus_bus_get");
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
fprintf (stderr, "Dbus: not primary owner, ret = %d\n", ret);
exit (1);
}
#if 1
dbus_error_init(&dbus_error);
if (!dbus_connection_add_filter (conn, ws_dbus_message_handler, NULL, NULL)) {
fprintf(stderr, "dbus_connection_add_filter\n");
exit(1);
}
while (dbus_connection_read_write_dispatch (conn, -1));
return 0;
#endif
#if 0
// Handle request from clients
while (1) {
// Block for msg from client
if (!dbus_connection_read_write_dispatch (conn, -1)) {
fprintf (stderr, "Not connected now.\n");
exit (1);
}
DBusMessage *message;
if ((message = dbus_connection_pop_message (conn)) == NULL) {
fprintf (stderr, "Did not get message\n");
continue;
}
if (dbus_message_is_method_call (message, INTERFACE_NAME, METHOD_NAME)) {
char *s;
bool error = false;
if (dbus_message_get_args (message, &dbus_error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) {
fprintf (stderr,"Get date from client: %s\n", s);
if (!error) {
// send reply
DBusMessage *reply;
char answer [40];
sprintf (answer, "I have get your message!");
if ((reply = dbus_message_new_method_return (message)) == NULL) {
fprintf (stderr, "Error in dbus_message_new_method_return\n");
exit (1);
}
DBusMessageIter iter;
dbus_message_iter_init_append (reply, &iter);
char *ptr = answer;
if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &ptr)) {
fprintf (stderr, "Error in dbus_message_iter_append_basic\n");
exit (1);
}
if (!dbus_connection_send (conn, reply, NULL)) {
fprintf (stderr, "Error in dbus_connection_send\n");
exit (1);
}
dbus_connection_flush (conn);
dbus_message_unref (reply);
}
else // There was an error
{
DBusMessage *dbus_error_msg;
char error_msg [] = "Error in input";
if ((dbus_error_msg = dbus_message_new_error (message, DBUS_ERROR_FAILED, error_msg)) == NULL) {
fprintf (stderr, "Error in dbus_message_new_error\n");
exit (1);
}
if (!dbus_connection_send (conn, dbus_error_msg, NULL)) {
fprintf (stderr, "Error in dbus_connection_send\n");
exit (1);
}
dbus_connection_flush (conn);
dbus_message_unref (dbus_error_msg);
}
}
else
{
print_dbus_error ("Error getting message");
}
}
}
return 0;
#endif
}
static DBusHandlerResult ws_dbus_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data)
{
DBusMessage *reply = NULL;
const char * path =dbus_message_get_path(message);
if(NULL==path){
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
if (strcmp(path,OBJECT_PATH_NAME) == 0) {
if (dbus_message_is_method_call(message,INTERFACE_NAME,METHOD_NAME)) {
char *s;
if (dbus_message_get_args (message, &dbus_error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) {
fprintf (stderr,"Get date from client: %s\n", s);
}
char answer [40];
sprintf (answer, "I have get your message!");
if ((reply = dbus_message_new_method_return (message)) == NULL) {
fprintf (stderr, "Error in dbus_message_new_method_return\n");
exit (1);
}
DBusMessageIter iter;
dbus_message_iter_init_append (reply, &iter);
char *ptr = answer;
if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &ptr)) {
fprintf (stderr, "Error in dbus_message_iter_append_basic\n");
exit (1);
}
}
}
if(reply){
// send the reply && flush the connection
if (!dbus_connection_send(connection, reply, NULL)) {
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
dbus_connection_flush(connection);
// free the reply
dbus_message_unref(reply);
return DBUS_HANDLER_RESULT_HANDLED ;
}else{
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
}
void print_dbus_error (char *str)
{
fprintf (stderr, "%s: %s\n", str, dbus_error.message);
dbus_error_free (&dbus_error);
}
Makefile
CC=gcc
CFLAGS=-Wall `pkg-config --cflags dbus-1`
LIBS=`pkg-config --libs dbus-1`
all: client server t-client
%.o: %.c
gcc -c $(CFLAGS) $^ -o $@
t-client: t-client.o
$(CC) $^ -o $@ $(LIBS)
client: client.o
$(CC) $^ -o $@ $(LIBS)
server: server.o
$(CC) $^ -o $@ $(LIBS)
.PHONY: clean
clean:
rm *.o client server t-client
org.freedesktop.DBus 的12个Methods简要说明
https://blog.csdn.net/MayOuyang/article/details/4566881
这篇文章很好,介绍的很全面
https://www.softprayog.in/programming/d-bus-tutorial
https://blog.csdn.net/eastmoon502136/article/details/10044993
https://blog.csdn.net/Kevin__Mei/article/details/89484314
来源:CSDN
作者:lavg_i
链接:https://blog.csdn.net/lavg_i/article/details/103139116