binder 通信


     PBbinder: 很简单,就是客户端要访问服务端的时候需要的工具
    Bbinder :  同上相反
    这里我个人理解是这两个东西就像是两个端口,就像是socket里面的端口号类似,实际代码中调用的通讯方法还不是这个。
   
    好了,开始介绍上面的流程,在Android的世界里,都是客户端通过服务端请求到数据来完成工作的,所以这就需要一个想servicemanager一样的管理模块来管理service。
具体的代码流程就不说了,网上多的事,主要通过接口调用来讲解使用方法.
    当客户端要像服务端请求数据的时候,都需要像servicemanager询问服务信息,当然了,这个服务信息需要在创建服务的时候进行注册,android在启动的时候,会运行所有的服务进程,而这些服务进程的创建过程中就完成了向servicemanager的注册工作
    int main() {

  sp<ProcessState> proc(ProcessState::self());
    //get service manager

       sp<IServiceManager> sm= defaultServiceManager();

       sm->addService(String16("service.testmanager"),new Test()); //这里注册自己的binder servers

      ProcessState::self()->startThreadPool();

      IPCThreadState::self()->joinThreadPool();

}  

    sp < IServiceManager >  sm  =  defaultServiceManager ( )   
       这个函数就是用来获取IServiceManager的子类对象的。这里可能有点疑惑 这个是什么东西,看过源码的话就会比较清楚,其实 defaultServiceManager就是通过servicemanager的binder号0来获取到BPServiceManager这个类的,而这个类其实就是真正用于通信用的接口类.
   这个类和IServiceManager稍后再说,往下看,addService就是增加自定义的服务接口了,注意到后面的new Test了吗 这个也稍后再说,这里就是注册服务了。
   前面提到了IServiceManager,那这个到底是什么呢?其实andorid里是通过创建一个纯虚的接口,随后使客户端和服务端的业务都用同一套,具体设计原因不清楚,在我浏览源码的过程中总结下来就是你不得不用I开头来创建你自己的春虚类,应为andorid对此做了限制,这点稍后再说。
   源码进去看到最后就会发现defaultServiceManager返回回来的正是重载了IServicemanager方法的子类。所以知道了吧。addservice其实就是一个用于像servicemanager服务通信的借口,通过这个借口想服务器发送注册信息完成注册。
        那BPserviceManager这个子类又是干什么的呢?这个子类也是需要完全按照android的框架来实现。
       有了这些概念
        现在通过代码来看看具体的实现:
        

namespace android

{

        class ITest : public IInterface

        {

                public:

                        DECLARE_META_INTERFACE(Test);

                        virtual void getTest()= 0;

        };

        class BnTest:public BnInterface<ITest>

        {

                public:

                        virtual status_t onTransact( uint32_t code,

                                        const Parcel& data,

                                        Parcel* reply,

                                        uint32_t flags = 0);

        };


}

        这个头文件是服务端和客户端都会用公用接口类,可以看到是用I开头的。 DECLARE_META_INTERFACE ( Test ) ;这个宏就是andorid的限制所在了,里面主要是申明了一个很重要的接口,用于返回Bpxxx对象,这个对象的作用之前也了解过了就是通信用的接口类。
    BnTest这个类的创建,可以发现也是继承自ITest,这个类是服务端的通信类,主要需要重载onTrancsact,这个函数用于接受客户端发来的消息已进行调用服务端重载接口来处理业务。
   


enum {

  PRINT = IBinder::FIRST_CALL_TRANSACTION,

  };

 

 class BpTest : public BpInterface<ITest>

 {

         public:

BpTest(const sp<IBinder>& impl):BpInterface<ITest>(impl)

 {


 }

virtual void getTest()

 {

 printf("in the get Test\n");

 Parcel data, reply;

data.writeInterfaceToken(ITest::getInterfaceDescriptor());

 remote()->transact(PRINT, data, &reply);

 printf("send Print %d\n",reply.readInt32());

 }

 

 };


 IMPLEMENT_META_INTERFACE(Test,"android.TestServer.ITest");



 status_t BnTest::onTransact(uint32_t code,const Parcel& data, Parcel* reply, uint32_t flags)

{


switch(code)

 {

 case PRINT:

 {

 printf("got the client msg\n");

CHECK_INTERFACE(ITest, data, reply);

getTest();

 reply->writeInt32(100);

 return NO_ERROR;

 

 }break;

 default:break;

 }

 return NO_ERROR;

 }


     源文件的实现可以很清楚的发现,Bptest重载了ITest里的get方法,这个方法就是给客户端用的,而onTrancat函数就是处理客户端发送过来的消息已实现逻辑业务处理的,而getTest()这个函数的调用其实就是调用的服务端继承ITest的方法,那这个方法是那里实现的呢?
    

namespace android

{

        class Test : public BnTest

        {

                public:

                        Test();

                        ~Test();

                        void getTest();

                        void print();

                                                                      

        };

}


    原来是在我们自己创建的服务端的处理类的时候继承Bntest,重载ITest的方法,那是怎么在运行的时候,BnTest知道要调用重载的方法呢? 原来就是在之前注册服务的时候new Test()的时候通知到的。
  现在就清楚了,接下来就是处理消息返回给客户端的事情了
  

 

case PRINT:

  {

 printf("got the client msg\n");

  CHECK_INTERFACE(ITest, data, reply);

  getTest();

  reply->writeInt32(100);

  return NO_ERROR;

  }break;


    android中通过parcel类来打包数据通过binder进行传输,所以上面的代码在接受到print消息之后就会执行一系列操作,
    而客户端在发送消息后也是从parcel中获取到返回消息的
    


virtual void getTest()

  {

  printf("in the get Test\n");

 Parcel data, reply;

  data.writeInterfaceToken(ITest::getInterfaceDescriptor());

remote()->transact(PRINT, data, &reply);

  printf("send Print %d\n",reply.readInt32());

  }

    这里有个地方要注意,remote()这个函数其实返回的就是pbbinder,所以最后看到还是要通过bninder发送消息。
   
       


root@android:/data #./Test&

[1] 893

root@android:/data #./Testclient

in the get Test

got the client msg

wahahaha

send Print 100

    机器运行效果如上,起了服务端后,启动客户端,进行通信。 个人总结,参考就可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其binder是重之重,都说无binder无Android,binde是Android系统的任督二脉。课程水平循序渐进,由级再到高级,满足各个层次水平的android开发者。1、灵活使用binder跨进程通信,在app端对它的任何api方法等使用自如2、可以单独分析android系统源码任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上层的java app端一直到最底层的内核binder驱动,都可以顺利理通5、针对系统开发过程遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码使用的socket源码轻松掌握9、android系统源码最常见的socketpair双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值