使用 dbus 的简单客户端服务器

Posted

技术标签:

【中文标题】使用 dbus 的简单客户端服务器【英文标题】:Simple client server using dbus 【发布时间】:2016-09-03 02:43:23 【问题描述】:

我已经使用 dbus 开发了一个客户端服务器应用程序。客户端使用 dbus_message 发送 2 个输入参数,服务器返回总和。我主要对使用 DBusWatch 感兴趣,因此我可以从多个客户端发送并让服务器响应它们。谁能帮我编写代码并解释一下 DbusWatch 是如何工作的?

代码

client.c

#include <stdio.h>
#include <stdlib.h>
#include <dbus/dbus.h>
#include <stdbool.h>
#include <ctype.h>
void caller(int param,int param1)

   DBusMessage* msg;
   DBusMessageIter args;
   DBusConnection* conn;
   DBusError err;
   DBusPendingCall* pending;
   int ret;
   int level;

   printf("Calling remote method with %d %d\n",param,param1);

   // initialiset the errors
   dbus_error_init(&err);

   // connect to the system bus and check for errors
   conn = 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 (NULL == conn)  
      exit(1); 
   

   // request our name on the bus
   ret = dbus_bus_request_name(conn, "test.client.caller", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
   if (dbus_error_is_set(&err))  
      fprintf(stderr, "Name Error (%s)\n", err.message); 
      dbus_error_free(&err);
   

   // create a new method call and check for errors
   msg = dbus_message_new_method_call("test.server.source", // target for the method call
                                      "/test/method/Object", // object to call on
                                      "test.method.Type", // interface to call on
                                      "Method"); // method name
   if (NULL == msg)  
      fprintf(stderr, "Message Null\n");
      exit(1);
   

   // append arguments
   dbus_message_iter_init_append(msg, &args);
   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &param)) 
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   

   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &param1)) 
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   

   // send message and get a handle for a reply
   if (!dbus_connection_send_with_reply (conn, msg, &pending, -1))  // -1 is default timeout
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   
   if (NULL == pending)  
      fprintf(stderr, "Pending Call Null\n"); 
      exit(1); 
   
   dbus_connection_flush(conn);

   printf("Request Sent\n");

   // free message
   dbus_message_unref(msg);

   // block until we recieve a reply
   dbus_pending_call_block(pending);

   // get the reply message
   msg = dbus_pending_call_steal_reply(pending);
   if (NULL == msg) 
      fprintf(stderr, "Reply Null\n"); 
      exit(1); 
   
   // free the pending message handle
   dbus_pending_call_unref(pending);

   // read the parameters
   if (!dbus_message_iter_init(msg, &args))
      fprintf(stderr, "Message has no arguments!\n"); 
   else
      dbus_message_iter_get_basic(&args, &level);

   printf("Got Reply:%d\n",level);

   // free reply and close connection
   dbus_message_unref(msg);   
  dbus_connection_close(conn);




int main(int argc, char **argv)

if (argc == 1)
        return -1;
else if(argc==3)

 int param = atoi(argv[1]);
 int param1 = atoi(argv[2]);
 caller(param,param1);

else
 
printf("Number of arguments should be 2 integers\n");


server.c

#include <stdbool.h>
#include <stdlib.h>              
#include <dbus/dbus-glib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <dbus-1.0/dbus/dbus.h>
#include <math.h>
void reply_to_method_call(DBusMessage* msg, DBusConnection* conn)

   DBusMessage* reply;
   DBusMessageIter rootIter;
   dbus_uint32_t serial = 0;
   dbus_uint32_t a;
   dbus_uint32_t b;
   dbus_uint32_t sum;

   // read the arguments
   if (!dbus_message_iter_init(msg,&rootIter))
      fprintf(stderr, "Message has no arguments!\n");
    dbus_message_iter_get_basic(&rootIter, &a);
    printf("Method called with %d\n", a);
    if(dbus_message_iter_has_next(&rootIter))
    
        dbus_message_iter_next(&rootIter);
        dbus_message_iter_get_basic(&rootIter, &b);
        printf("Method called with %d\n", b);
    

   if ( dbus_message_is_method_call( msg, "test.method.Type", "Method" ) ) 

    sum=a+b; 
 
  // create a reply from the message
   reply = dbus_message_new_method_return(msg);

   // add the arguments to the reply
   dbus_message_iter_init_append(reply, &rootIter);

   if (!dbus_message_iter_append_basic(&rootIter, DBUS_TYPE_INT32, &sum))  
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);

   

   // send the reply && flush the connection
   if (!dbus_connection_send(conn, reply, &sum)) 
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   
   dbus_connection_flush(conn);

   // free the reply
   dbus_message_unref(reply);


int main()

 DBusMessage* msg;
   DBusMessage* reply;
   DBusMessageIter args;
   DBusConnection* conn;
   DBusError err;
   int ret;
   char* param;

   printf("Listening for method calls\n");

   // initialise the error
   dbus_error_init(&err);

   // connect to the bus and check for errors
   conn = 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 (NULL == conn) 
      fprintf(stderr, "Connection Null\n"); 
      exit(1); 
   

   // request our name on the bus and check for errors
   ret = dbus_bus_request_name(conn,"test.server.source", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
   if (dbus_error_is_set(&err))  
      fprintf(stderr, "Name Error (%s)\n", err.message); 
      dbus_error_free(&err);
   


   // loop, testing for new messages
   while (true) 
      // non blocking read of the next available message
      dbus_connection_read_write(conn, 0);
      msg = dbus_connection_pop_message(conn);

      // loop again if we haven't got a message
      if (NULL == msg)  
         sleep(1); 
         continue; 
      

      if ( dbus_message_has_interface(msg, "test.method.Type") )
        reply_to_method_call( msg, conn );
      // free the message
      dbus_message_unref(msg);
   

   // close the connection
   dbus_connection_close(conn);

【问题讨论】:

【参考方案1】:

以及构建这些文件的 Makefile;

CC=gcc
CPP=g++

LDFLAGS =-ldbus-1
LDFLAGS+=-ldbus-glib-1

CFLAGS =.
CFLAGS+=-I/usr/include/dbus-1.0
CFLAGS+=-I/usr/lib/x86_64-linux-gnu/dbus-1.0/include
CFLAGS+=-I/usr/include/glib-2.0
CFLAGS+=-I/usr/lib/x86_64-linux-gnu/glib-2.0/include

CFLAGS+=-Wall
CFLAGS+=-Wextra
CFLAGS+=-g


all: server client

rebuild: clean all

%.o: %.c
    @echo "    CC $^"
    $(CC) $(CFLAGS) -c -o $@ $^

server: server.o
    @echo "    LINK $^"
    $(CC) $^ $(LDFLAGS) -o $@

client: client.o
    @echo "    LINK $^"
    $(CC) $^ $(LDFLAGS) -o $@

clean:
    rm -f *.o server client

【讨论】:

您能否提供更多背景信息,说明您的答案为何以及如何帮助 OP?

以上是关于使用 dbus 的简单客户端服务器的主要内容,如果未能解决你的问题,请参考以下文章

服务器和客户端中不同的 Dbus 绑定

DBus 同步调用超时

简单(但具体)的侦听器和发送器 Python 3 DBus 示例

Open*** v3 Dbus 客户端未接收到所有信号

dbus总是需要总线吗

Dbus/GLib 主循环,后台线程