美文网首页
微信Mars跨平台组件iOS端消息调用流程

微信Mars跨平台组件iOS端消息调用流程

作者: CoderQH | 来源:发表于2017-06-03 12:18 被阅读2335次

    摘要

    Mars 是微信官方的终端基础组件,是一个使用 C++ 编写的业务性无关,平台性无关的基础组件。目前已接入微信 Android、iOS、Mac、Windows、WP 等客户端。下面主要分析iOS端样例消息调用流程。

    Mars 结构

    官方样图官方样图
    • COMM:基础库,包括socket、线程、消息队列、协程等基础工具;
    • XLOG:通用日志模块,充分考虑移动终端的特点,提供高性能、高可用、安全性、容错性的日志功能;
    • SDT:网络诊断模块;
    • STN:信令传输网络模块,负责终端与服务器的小数据信令通道。包含了微信终端在移动网络上的大量优化经验与成果,经历了微信海量用户的考验。

    其中STN(信令传输网络)为核心模块。

    下面主要分析STN模块消息通讯流程:

    消息核心流程:一个消息任务以startTask开始,onTaskEnd结束。中间通过StnCallBack::Req2Buf与StnCallBack::Buf2Resp分别处理客户端的请求和响应的相关操作,比如数据处理,服务端响应和状态检测等等。

    客户端发送/接受

    发送

    数据传输格式为:google 的 protocol buffer。protocol buffer是google的一个开源项目,它是用于结构化数据串行化的灵活、高效、自动的方法,例如XML,不过它比xml更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。

    iOS端发送调用方法: requestSendData

    -(NSData*)requestSendData {
        SendMessageRequest *sendMsgRequest = [SendMessageRequest new];
        sendMsgRequest.from = [self username];
        sendMsgRequest.to = @"all";
        sendMsgRequest.text = _textField.text;
        sendMsgRequest.accessToken = @"123456";
        sendMsgRequest.topic = _conversation.topic;
        LOG_INFO(kModuleViewController, @"send msg to topic:%@", _conversation.notice);
        NSData* data = [sendMsgRequest data];
        dispatch_async(dispatch_get_main_queue(), ^{
            _textField.text = @"";
        });
        return data;
    }
    
    

    数据处理:StnCallBack::Req2Buf

    bool StnCallBack::Req2Buf(int32_t _taskid, void* const _user_context, AutoBuffer& _outbuffer, int& _error_code, const int _channel_select) {
        NSData* requestData =  [[NetworkService sharedInstance] Request2BufferWithTaskID:_taskid userContext:_user_context];
        
        if (requestData == nil) {
            requestData = [[NSData alloc] init];
        }
    
        _outbuffer.AllocWrite(requestData.length);
        _outbuffer.Write(requestData.bytes,requestData.length);
        return requestData.length > 0;
    }
    
    
    接收
    -(int)onPostDecode:(NSData*)responseData {
        SendMessageResponse *sendMsgResponse = [SendMessageResponse parseFromData:responseData error:nil];
        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *recvtext = [NSString stringWithFormat:@"%@ : %@", sendMsgResponse.from, sendMsgResponse.text];
            [self.messages addObject:recvtext];
            [self.tableView reloadData];
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.messages.count-1 inSection:0];
            [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
        });
        return sendMsgResponse.errCode == 0 ? 0 : -1;
    }
    

    数据处理:StnCallBack::Buf2Resp

    int StnCallBack::Buf2Resp(int32_t _taskid, void* const _user_context, const AutoBuffer& _inbuffer, int& _error_code, const int _channel_select) {
        
        int handle_type = mars::stn::kTaskFailHandleNormal;
        NSData* responseData = [NSData dataWithBytes:(const void *) _inbuffer.Ptr() length:_inbuffer.Length()];
        
        NSInteger errorCode = [[NetworkService sharedInstance] Buffer2ResponseWithTaskID:_taskid ResponseData:responseData userContext:_user_context];
        
        if (errorCode != 0) {
            handle_type = mars::stn::kTaskFailHandleDefault;
        }
        
        return handle_type;
    }
    
    消息存储

    消息存储是用字典存储,taskID为key,数据包为value。

    - (void)addObserver:(id<UINotifyDelegate>)observer forKey:(NSString *)key {
        [controllers setObject:observer forKey:key];
    }
    
    - (void)addCGITasks:(CGITask*)cgiTask forKey:(NSString *)key {
        [tasks setObject:cgiTask forKey:key];
    }
    
    

    服务端推送

    当TaskID 为0时候,默认为推送。

    调用方法:notifyPushMessage

    
    - (void)notifyPushMessage:(NSData*)pushData withCmdId:(int)cmdId {
        MessagePush* messagePush = [MessagePush parseFromData:pushData error:nil];
        if (messagePush != nil) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSString *recvtext = [NSString stringWithFormat:@"%@ : %@", messagePush.from, messagePush.content];
                [self.messages addObject:recvtext];
                [self.tableView reloadData];
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.messages.count-1 inSection:0];
                [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
            });
        }
    }
    

    数据处理:StnCallBack::OnPush

    void StnCallBack::OnPush(int32_t _cmdid, const AutoBuffer& _msgpayload) {
        if (_msgpayload.Length() > 0) {
            NSData* recvData = [NSData dataWithBytes:(const void *) _msgpayload.Ptr() length:_msgpayload.Length()];
            [[NetworkService sharedInstance] OnPushWithCmd:_cmdid data:recvData];
        }
        
    }
    
    

    数据存储:cmdID

    - (void)addPushObserver:(id<PushNotifyDelegate>)observer withCmdId:(int)cmdId {
        LOG_INFO(kNetwork, @"add pushObserver for cmdId:%d", cmdId);
        [pushrecvers setObject:observer forKey:[NSString stringWithFormat:@"%d", cmdId]];
    }
    

    完成一个任务

    调用方法:

    - (int)onTaskEnd:(uint32_t)tid errType:(uint32_t)errtype errCode:(uint32_t)errcode {
        
        NSLog(@"%ld  %ld  %ld ",tid, errtype, errcode);
        
        return 0;
    }
    

    处理方法:StnCallBack::OnTaskEnd

    int  StnCallBack::OnTaskEnd(int32_t _taskid, void* const _user_context, int _error_type, int _error_code) {
        
        return (int)[[NetworkService sharedInstance] OnTaskEndWithTaskID:_taskid userContext:_user_context errType:_error_type errCode:_error_code];
    
    }
    
    

    待续。

    相关文章

      网友评论

          本文标题:微信Mars跨平台组件iOS端消息调用流程

          本文链接:https://www.haomeiwen.com/subject/tqvjfxtx.html