微信开源mars源码分析2—上层samples分析(续)

本来是想直接深入到mars的核心层去看的,但是发现其实上面的samples部分还有好些没有分析到,因此回来继续分析。
ConversationActivity这个类中实际上还做了很多的工作,在onCreate中:

final MainService mainService = new MainService();
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.CGIHISTORY_CMDID, mainService);
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.CONNSTATUS_CMDID, mainService);
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.FLOW_CMDID, mainService);
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.PUSHMSG_CMDID, mainService);
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.SDTRESULT_CMDID, mainService);

这里出现了一个MainService,我们来看看:
/mars-master/samples/android/marsSampleChat/app/src/main/java/com/tencent/mars/sample/core/MainService.java

public class MainService implements PushMessageHandler {
        
            public static String TAG = "Mars.Sample.MainService";
        
            private Thread recvThread;
        
            private LinkedBlockingQueue<PushMessage> pushMessages = new LinkedBlockingQueue<>();
        
            private BusinessHandler[] handlers = new BusinessHandler[]{
                    new MessageHandler(),
                    new StatisticHandler()
            };
        
            public MainService() {
                this.start();
            }
        
            public void start() {
                if (recvThread == null) {
                    recvThread = new Thread(pushReceiver, "PUSH-RECEIVER");
        
                    recvThread.start();
                }
            }
        
            private final Runnable pushReceiver = new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            PushMessage pushMessage = pushMessages.take();
                            if (pushMessage != null) {
                                for (BusinessHandler handler : handlers) {
                                    if (handler.handleRecvMessage(pushMessage)) {
                                        break;
                                    }
                                }
                            }
        
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e1) {
                                //
                            }
                        }
                    }
                }
            };
        
            @Override
            public void process(PushMessage message) {
                pushMessages.offer(message);
            }
        }
1.启动了一个接受者线程pushReceiver;
2.pushReceiver从LinkedBlockingQueue<PushMessage>的pushMessages中不断获取message,然后通知到handlers的每个成员中,handlers是这样定义的:
private BusinessHandler[] handlers = new BusinessHandler[]{
                new MessageHandler(),
                new StatisticHandler()
        };
继续往下看MessageHandler:
/mars-master/samples/android/marsSampleChat/app/src/main/java/com/tencent/mars/sample/core/MessageHandler.java
public class MessageHandler extends BusinessHandler{
    
        public static String TAG = MessageHandler.class.getSimpleName();
    
        @Override
        public boolean handleRecvMessage(PushMessage pushMessage) {
    
            switch (pushMessage.cmdId) {
                case Constants.PUSHCMD:
                {
                    try {
                        Messagepush.MessagePush message = Messagepush.MessagePush.parseFrom(pushMessage.buffer);
                        Intent intent = new Intent();
                        intent.setAction(Constants.PUSHACTION);
                        intent.putExtra("msgfrom", message.from);
                        intent.putExtra("msgcontent", message.content);
                        intent.putExtra("msgtopic", message.topic);
                        SampleApplicaton.getContext().sendBroadcast(intent);
                    } catch (InvalidProtocolBufferNanoException e) {
                        Log.e(TAG, "%s", e.toString());
                    }
                }
                    return true;
                default:
                    break;
            }
    
            return false;
        }
    }

如果是Constants.PUSHCMD类型的message,那么就发送一个广播。这个广播实际上会由Mars核心部分接收到,但是传递的intent参数其实没有意义,核心部分只是根据每次的pushcmd进行网络状态的检查而已,这些后话我们在分析核心的时候再说。
另外一个StatisticHandler,是专用于统计的,我们暂时不去关注。
让我们回到ConversationActivity,在MainService的new之后,会调用MarsServiceProxy.setOnPushMessageListener多次,设置监听,我们来看看MarsServiceProxy里面如何运转:

public static void setOnPushMessageListener(int cmdId, PushMessageHandler pushMessageHandler) {
    if (pushMessageHandler == null) {
        inst.pushMessageHandlerHashMap.remove(cmdId);
    } else {
        inst.pushMessageHandlerHashMap.put(cmdId, pushMessageHandler);
    }
}

添加了监听到一个支持高并发的hashmap中:

private ConcurrentHashMap<Integer, PushMessageHandler> pushMessageHandlerHashMap = new ConcurrentHashMap<>();
private MarsPushMessageFilter filter = new MarsPushMessageFilter.Stub() {

    @Override
    public boolean onRecv(int cmdId, byte[] buffer) throws RemoteException {
        PushMessageHandler handler = pushMessageHandlerHashMap.get(cmdId);
        if (handler != null) {
            Log.i(TAG, "processing push message, cmdid = %d", cmdId);
            PushMessage message = new PushMessage(cmdId, buffer);
            handler.process(message);
            return true;

        } else {
            Log.i(TAG, "no push message listener set for cmdid = %d, just ignored", cmdId);
        }

        return false;
    }
};

可以看到,这里创建了一个filter,这个filter在接收到一个cmd后,根据id查找到PushMessageHandler,然后调用hander.process,传递参数PushMessage,这个PushMessage实际上又是由cmdid和buffer组成的。这里的cmdid理解为一个指令的类型id即可。再到MainService中的process,其实就是加入PushMessage的一个队列中等待处理。
回来看filter在何时调用的吧。
首先在MarsServiceProxy的onServiceConnected:

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    Log.d(TAG, "remote mars service connected");

    try {
        service = MarsService.Stub.asInterface(iBinder);
        service.registerPushMessageFilter(filter);
        service.setAccountInfo(accountInfo.uin, accountInfo.userName);

    } catch (Exception e) {
        service = null;
    }
}

看到了吧,将这个filter注册到了服务中。来吧,MarsServiceNative的registerPushMessageFilter:

@Override
public void registerPushMessageFilter(MarsPushMessageFilter filter) throws RemoteException {
    stub.registerPushMessageFilter(filter);
}

到了MarsServiceStub里:

@Override
public void registerPushMessageFilter(MarsPushMessageFilter filter) throws RemoteException {
    filters.remove(filter);
    filters.add(filter);
}

加入了filters的队列中,然后在onPush中有所调用:

@Override
public void onPush(int cmdid, byte[] data) {
    for (MarsPushMessageFilter filter : filters) {
        try {
            if (filter.onRecv(cmdid, data)) {
                break;
            }

        } catch (RemoteException e) {
            //
        }
    }
}

这里调用了每个filter的onRecv方法,这样就和上面的串起来了吧。那么何时调用的这个onPush呢,答案在核心mars部分的StnLogic里面,这里规定了一个ICallBack,里面有onPush,会在适当的时候调用。具体的内容我会在后面的mars核心层分析的时候指出。

总结一下:
MainService在一开始启动,并且启动专门的线程处理接收到的pushMessage,处理的过程就是调用之前已经准备好的一个handler的队列的每个项目的handleRecvMessage,其中的MessageHandler会发送广播通知mars有pushcmd来了。
另一方面,MainService提供process调用向message队列中加入新项目。这个加入的过程调用在MarsServiceProxy中进行,内部生成了一个filter过滤器,并将其注册到服务MarsServiceNative中,MarsServiceNative其实也是走的MarsServiceStub,在他里面维护的filter的队列,并且MarsServiceStub还是底层核心Mars的回调监听者,在onPush到来的时候,依次调用filter队列中的各个项目的onRecv方法来实现通知。在filter的onRecv方法中就实现了handler.process(message),通知到了handler。

现在对于这部分应该比较明晰了吧。准备下一篇进行Mars的核心层分析吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mars微信官方的终端基础组件,是一个使用 C 编写的业务性无关、平台性无关的基础组件。目前已接入微信 Android、iOS、Mac、Windows、WP 等客户端。主要包括以下几个部分:COMM:基础库,包括socket、线程、消息队列、协程等基础工具;XLOG:通用日志模块,充分考虑移动终端的特点,提供高性能、高可用、安全性、容错性的日志功能;SDT:网络诊断模块;STN:信令传输网络模块(核心模块),负责终端与服务器的小数据信令通道。包含了微信终端在移动网络上的大量优化经验与成果,经历了微信海量用户的考验。Mars 最早起微信的实际发展需要。由于微信多平台、亿级用户,微信基础功能的修改影响重大。但不同平台不同的实现导致众多平台上很难统一,一方面不利于质量把关,可能存在重大隐患,一方面也不利于微信对基础研究的深入。因此,微信开始了跨平台基础组件的开发,并且在微信中沉淀多年。随着基础组件的发展与稳定,他们希望通过开源的力量进一步的提升微信的基础,并且也期待行业的互相交流与促进,因此启动了Mars项目。微信的网络层设计到很多不同的业务,在微信中使用到的绝大部分功能,都是基于Mars提供的网络组件,包括文本消息、语音消息、朋友圈等核心功能。只有少部分业务不在范围内,例如VOIP、Webview等。微信中使用到的网络服务,大体分为两种类型:信令网络、数据网络。其中STN负责信令网络,CDN组件则负责数据网络。但由于CDN涉及到腾讯内部的CDN服务,因此在Mars开源列表中并没有包含CDN部分。SDT网络诊断模块提供了最基础的检测能力,需要由使用者自己组合使用。各个平台的Reachability API能反映的情况有局限,无法应对复杂的网络诊断,事实上有一些开源项目就是为了替换系统API。微信由于自身特点对网络诊断要求很高,因此将它作为基础的跨平台组件进行开发维护。STN是微信的信令传输网络,也可以认为是小数据传输网络,是微信日常中使用最频繁的网络通道。在开源设计上,STN抽象了微信的使用模型,使得STN成为业务无关的网络通道,并且应用到了包括微信在内的多个腾讯内部应用中。与AFNetworking、Retrofit、Okhttp等框架不同,STN不仅是跨平台的网络解决框架,更是着重了“移动互联网“这一特点,结合移动互联网的不稳定特性,做了大量的优化工作,并且这些优化都是经过了微信长时间的验证和使用的。除此之外,STN中还包含了很多其他方面的实用设计,包括自定义DNS、容灾设计、负载考量、APP的前后台考量、休眠机制考量、省电机制等等。STN 比其它网络框架提供更多的功能:数据监控:STN提供了许多数据回调接口,使得应用可以基于这些网络数据,建立统计分析、监控等工具来管理应用的实际网络情况;问题定位:STN中含有很多关键日志,并且日志的设计已经帮助微信定位了很多的网络层问题。结合Mars提供的XLOG日志机制,应用可以运行时也打开日志,非常方便定位;参数配置:STN中将很多参数抽离为配置,使得应用可以根据自己的情况进行修改。网络通道上,目前STN提供了长连、短连两种类型的通道,用于满足不同的需求。使用STN后,应用开发者只需关注业务开发。移动互联网的各种“坑”则可以交由STN帮你处理。 标签:腾讯  微信

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值