Common API学习

1 CommonAPI

         some/IP(Scalable service-Oriented MiddlewarE over IP) 是一种用于SOA的架构的汽车整车通信协议,该协议是由德国宝马公司提出。 GitHub - COVESA/vsomeip: An implementation of Scalable service-Oriented MiddlewarE over IP          commonAPI 是一个进程间通信框架,可以支持dbus,和some IP,这个框架对C++支持很好。 CommonAPI C++ 在通讯层分为Core和Binding两个部分。Core负责和Application交互,Binding负责和系统底层的IPC服务栈交互,其中的Binding即IPC的具体实现方式。目前GENIVI支持的Binding分为两种,分别是SOME/IP和DBus

CommonAPI C++的IPC接口使用的是通用的“服务端、客户端”模式。
对于客户端主动发起的通讯,采取的是方法(Methods)调用的方式来实现。
Method分为两种类型:
标准的带有返回值的Method(Basic Method)
不需要返回值的Method(Fire-and-forgot Method)

服务端主动发起的通讯通过广播(Broadcasts)的方式实现。
CommonAPI C++提供的广播模式也有两种:
标准的广播方式(Basic Broadcasts),即广播内容发送给所有的客户端
选择性广播方式(Selective Broadcasts),即广播内容可以发送给某一个或一组客户端。此种情况下,通常是由服务端提供类似Registor的Method用于客户端注册。然后服务端根据注册情况将广播发送给不同的客户端。

使用步骤:
1.首先下载源码,生成core、someip,dbus程序。
2.编写fidl文件
3.使用core程序去生成代码
4.使用dbus或者someip去生成代码


 

2 UNIX Domain socket
     socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(IP设置为127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。
      UNIX域套接字与TCP套接字相比较,在同一台主机的传输速度前者是后者的两倍。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。对于TCP套接字,许多客户端可以连接它并发送数据并关闭。 但是对于UNIX套接字,如果客户端关闭套接字,服务器端也将关闭。
      UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。

用法:

服务端: socket -> bind -> listen -> accept -> recv/send -> close 
客户端: socket -> connect -> recv/send -> close

         UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。
 

server 端程序:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/un.h>
#include<errno.h>
#include<stddef.h>
#include<unistd.h>

#define MAX_CONNECT_NUM 2
#define BUFFER_SIZE 1024
const char *filename="uds-tmp";

int main()
{
    int fd,new_fd,len,i;
    struct sockaddr_un un;
    fd = socket(AF_UNIX,SOCK_STREAM,0);
    if(fd < 0){
        printf("Request socket failed!\n");
        return -1;
    }
    un.sun_family = AF_UNIX;
    unlink(filename);
    strcpy(un.sun_path,filename);
    if(bind(fd,(struct sockaddr *)&un,sizeof(un)) <0 ){
        printf("bind failed!\n");
        return -1;
    }
    if(listen(fd,MAX_CONNECT_NUM) < 0){
        printf("listen failed!\n");
        return -1;
    }
    while(1){
        struct sockaddr_un client_addr;
        char buffer[BUFFER_SIZE];
        bzero(buffer,BUFFER_SIZE);
        len = sizeof(client_addr);
        //new_fd = accept(fd,(struct sockaddr *)&client_addr,&len);
        new_fd = accept(fd,NULL,NULL);
        if(new_fd < 0){
            printf("accept failed\n");
            return -1;
        }
        int ret = recv(new_fd,buffer,BUFFER_SIZE,0);
        if(ret < 0){
            printf("recv failed\n");
        }
        for(i=0; i<10; i++){
            printf(" %d",buffer[i]);
        }
        close(new_fd);
        break;
    }
    close(fd);
}

client 端程序:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/un.h>
#include<errno.h>
#include<stddef.h>
#include<unistd.h>
#define BUFFER_SIZE 1024
const char *filename="uds-tmp";

int main()
{
    struct sockaddr_un un;
    int sock_fd;
    char buffer[BUFFER_SIZE] = {1,2,3};
    un.sun_family = AF_UNIX;
    strcpy(un.sun_path,filename);
    sock_fd = socket(AF_UNIX,SOCK_STREAM,0);
    if(sock_fd < 0){
        printf("Request socket failed\n");
        return -1;
    }
    if(connect(sock_fd,(struct sockaddr *)&un,sizeof(un)) < 0){
        printf("connect socket failed\n");
        return -1;
    }
    send(sock_fd,buffer,BUFFER_SIZE,0);

    close(sock_fd);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wangbuji/article/details/126269058