最近的工作涉及到DBUS通信,所以这里做一下总结,也是即学即用所以了解的没有那么深入,环境搭建这里就不谈了,这里说说具体的操作流程以及代码的实现。
我们这里按CS的模式来讲,我们这里会有两个C文件,一个是服务端代码,一个是客户端代码,对了还有一个XML文件。
首先当然是先写好这两个代码,然后就是编译了,编译首先先要编译这个XML文件,编译这个XML文件我们这里要利用到DBUS-BINDING-TOOL这个工具:
dbus-binding-tool --mode=glib-server --prefix=netsetserver netset.xml>netset_server.h
dbus-binding-tool --mode=glib-client --prefix=netsetserver netset.xml>netset_client.h
注意这两句只有MODE是不一样的,所以生成的头文件一个是客户端的一个是服务端的,这里举个NETSET.XML这个文件的示例:
<?xml version="1.0" encoding="UTF-8"?>
<node name="/test/example/server">
<interface name="test.example.ServerInterface">
<method name="getmacip">
<arg name="device" type="s" direction="in"/>
<arg name="macip" type="ay" direction="out"/>
</method>
</interface>
</node>
这里有一个节点node,里面包含一个接口interface,这个接口里头包含一个方法method,方法也就是函数啦,可以理解成这个函数是这样的getmacip(char *device,struct xxx macip),其中device是输入参数,macip是输出参数,注意我这里展示的是比较难的结构体的传递,数据类型是ay,这里涉及到一个用容器存储数据的技巧。
好了现在看看客户端是如何实现的:
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define MAXIPNUM 1024
typedef struct addr
{
unsigned char mac[20];
unsigned char ip[MAXIPNUM*16];
}Addr;
typedef struct testa
{
int a;
char b[20];
}Testa;
typedef struct testb
{
int c;
Testa t;
}Testb;
static void
lose(const char *str, ...)
{
va_list args;
va_start(args, str);
vfprintf(stderr, str, args);
fputc('/n', stderr);
va_end(args);
exit(1);
}
static void
lose_gerror(const char *prefix, GError *error)
{
if(error){
lose("%s: %s", prefix, error->message);
}
else{
lose("%s", prefix);
}
}
static void
usage()
{
printf("Usage: client getmacip device./n");
exit(1);
}
static void
getmacip(DBusGProxy *proxy, char *device)
{
GError *err=NULL;
GArray *macip=NULL;
GArray *arr=NULL;
Addr *ret;
Testb *tb;
if(!dbus_g_proxy_call(proxy, "getmacip", &err,
G_TYPE_STRING, device,
G_TYPE_INVALID,
dbus_g_type_get_collection("GArray",G_TYPE_UCHAR), &macip,
dbus_g_type_get_collection("GArray",G_TYPE_UCHAR), &arr,
G_TYPE_INVALID))
lose_gerror("Failed to getmacip", err);
else{
ret = (Addr*)macip->data;
tb = (Testb*)arr->data;
printf("The mac is: %s/nThe ip is: %s/n", ret->mac, ret->ip);
printf("The testb is: %d %d %s/n",tb->c, tb->t.a, tb->t.b);
g_array_free(macip,TRUE);
g_array_free(arr,TRUE);
}
}
int main(int argc, char *argv[])
{
DBusGConnection *bus;
GError *error=NULL;
g_type_init();
printf("Debug............................./n");
bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
if(!bus)
lose_gerror("Countn't connect to session bus", error);
if(argc == 1){
usage();
}
else if(0 == strcmp(argv[1],"getmacip") && argc == 3){
DBusGProxy *gmiproxy;
gmiproxy = dbus_g_proxy_new_for_name(bus, "test.example.Server",
"/test/example/Server", "test.example.ServerInterface");
getmacip(gmiproxy, argv[2]);
}
else{
usage();
}
exit(0);
}
服务端:
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/sockios.h>
#define MAXIPNUM 1024
#define MAXINTERFACES 1024
typedef struct Server Server;
typedef struct ServerClass ServerClass;
#define SERVER_TYPE (server_get_type())
GType server_get_type(void);
typedef struct addr
{
unsigned char mac[20];
unsigned char ip[MAXIPNUM*16];
}Addr;
typedef struct testa
{
int a;
char b[20];
}Testa;
typedef struct testb
{
int c;
Testa t;
}Testb;
struct Server
{
GObject parent;
};
struct ServerClass
{
GObjectClass parent;
};
enum
{
LAST_SIGNAL
};
G_DEFINE_TYPE(Server, server, G_TYPE_OBJECT);
gboolean server_getmacip(Server *obj, char *device, GArray **macip, GArray **arr, GError **error);
#include "server-glue.h"
static void
server_init(Server *obj)
{
}
static void
server_class_init(ServerClass *klass)
{
}
static void
lose(const char *str, ...)
{
va_list args;
va_start(args, str);
vfprintf(stderr, str, args);
fputc('/n', stderr);
va_end(args);
exit(1);
}
static void
lose_gerror(const char *prefix, GError *error)
{
if(error){
lose("%s: %s", prefix, error->message);
}
else{
lose("%s", prefix);
}
}
gboolean server_getmacip(Server *obj, char *device, GArray **macip, GArray **arr, GError **error)//这里的macip参数是一个结构体指针
{
char ips[MAXIPNUM][16];
char message[MAXIPNUM*16];
struct ifreq buf[MAXINTERFACES];
struct ifconf ifc;
int inter_num = 0;
int interface = 0;
int i = 0;
int sockfd;
char macaddr[6];
struct ifreq ifr;
struct sockaddr_in addr;
Addr result;
Testb tb;//如何测试
memset(&addr,0,sizeof(struct sockaddr_in));
memset(message,0,MAXIPNUM*16);
memset(&result,0,sizeof(Addr));
memset(&tb,0,sizeof(Testb));
*macip = g_array_new(FALSE,FALSE,sizeof(guint8));//容器
*arr = g_array_new(FALSE,FALSE,sizeof(guint8));
//*mac = g_new(char *, 20);
//*ip = g_new(char *, MAXIPNUM*16);
//*mac = (char *)g_malloc(sizeof(char)*20);
//*ip = (char *)g_malloc(sizeof(char)*MAXIPNUM*16);
if((sockfd = socket(PF_INET,SOCK_DGRAM,0)) == -1)
{
fprintf(stderr,"Sock Error: %s/n",strerror(errno));
}
memset(&ifr,0,sizeof(ifr));
strcpy(ifr.ifr_name,device);
if(ioctl(sockfd,SIOCGIFHWADDR,(struct ifreq*)&ifr) == -1)
{
fprintf(stderr,"ioctl SIOCGIFHWADDR Error: %s/n",strerror(errno));
close(sockfd);
}
memcpy(macaddr,ifr.ifr_hwaddr.sa_data,6);
sprintf((char*)result.mac,"%02x:%02x:%02x:%02x:%02x:%02x",(0xff&macaddr[0]),(0xff&macaddr[1]),(0xff&macaddr[2]),(0xff&macaddr[3]),(0xff&macaddr[4]),(0xff&macaddr[5]));
memset(buf, 0, sizeof(struct ifreq)*MAXINTERFACES);
ifc.ifc_len = sizeof(struct ifreq)*MAXINTERFACES;
ifc.ifc_buf = (caddr_t)buf;
if(!ioctl(sockfd, SIOCGIFCONF, (char *)&ifc))
{
inter_num = ifc.ifc_len/sizeof(struct ifreq);
while(interface < inter_num)
{
if(strcmp(buf[interface].ifr_name,device)!=0)
{
interface++;
continue;
}
if(ioctl(sockfd,SIOCGIFADDR, (char *)&buf[interface])==-1)
{
fprintf(stderr,"ioctl SIOCGIFADDR Error: %s/n",strerror(errno));
close(sockfd);
}
addr = *((struct sockaddr_in*)(&(buf[interface].ifr_addr)));
strcpy((char*)ips[i],(char*)inet_ntoa(addr.sin_addr));
sprintf((char*)result.ip, "%s%s", message, (char*)ips[i]);
sprintf(message, "%s/n", (char*)result.ip);
i++;
interface++;
}
}
close(sockfd);
tb.c = 5;
tb.t.a = 3;
strcpy(tb.t.b,"Hello World!");
g_array_append_vals(*macip, &result, sizeof(Addr));//addr是一个结构体
g_array_append_vals(*arr, &tb, sizeof(Testb));
//printf("Success to getmacip/n");
return TRUE;
}
int main(int argc, char *argv[])
{
DBusGConnection *bus;
DBusGProxy *bus_proxy;
GError *error=NULL;
GMainLoop *mainloop;
Server *obj;
guint request_name_result;
g_type_init();
dbus_g_object_type_install_info(SERVER_TYPE, &dbus_glib_server_object_info);
mainloop = g_main_loop_new(NULL, FALSE);
bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
if(!bus)
lose_gerror("Countn't connect to session bus", error);
bus_proxy = dbus_g_proxy_new_for_name(bus, "org.freedesktop.DBus",
"/org/freedesktop/DBus", "org.freedesktop.DBus");
if(!dbus_g_proxy_call(bus_proxy, "RequestName", &error,
G_TYPE_STRING, "test.example.Server",
G_TYPE_UINT, 0,
G_TYPE_INVALID,
G_TYPE_UINT, &request_name_result,
G_TYPE_INVALID))
lose_gerror("Failed to acquire test.example.Server", error);
obj = g_object_new(SERVER_TYPE, NULL);
dbus_g_connection_register_g_object(bus, "/test/example/Server", G_OBJECT(obj));
g_main_loop_run(mainloop);
exit(0);
}
编译是这样的:
gcc -Wall netset_server.c -g -o server_netset `pkg-config --libs --cflags dbus-glib-1`
gcc -Wall netset_client.c -g -o client_netset `pkg-config --libs --cflags dbus-glib-1`
注意这里的标点符号哦,很容易出错
对了在运行之前还要还要建立一个DBUS,否则无法通信:
[root@localhost homework]# dbus-launch
DBUS_SESSION_BUS_ADDRESS='unix:abstract=/tmp/dbus-EBop04REqN'
DBUS_SESSION_BUS_PID=1165
[root@localhost homework]# export DBUS_SESSION_BUS_ADDRESS='unix
这样导入一下就OK了,可以测试CS了
上面代码有些是固定的套路,今天不想写了,改天详细的解释一下每一句的意义