消息转发流程

消息转发流程

forwardingTargetForSelector 快速转发

- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
    return [Good new];
}

解析

  • 当对象goodOne中没有对应的方法实现,可以通过上面这个方法进行重定向,找一个对象顶替goodOne去实现对应调用的方法。
  • 方法名称要保持一致。

methodSignatureForSelector消息慢速转发

//// 慢速转发
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
    if (aSelector == @selector(name)) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    }
    return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
//    NSLog(@"%@ - %@",anInvocation.target,NSStringFromSelector(anInvocation.selector));
    Good *s = [Good alloc];
    if ([self respondsToSelector:anInvocation.selector]) {
        [anInvocation invoke];
    }else if ([s respondsToSelector:anInvocation.selector]){
        [anInvocation invokeWithTarget:s];
    }else{
        NSLog(@"%s - %@",__func__,NSStringFromSelector(anInvocation.selector));
    }
}

直接通过 forwardInvocation 将方法重定向到别的对象的方法
- (void)forwardInvocation:(NSInvocation *)anInvocation  
     Good *s = [Good alloc];
     anInvocation.target = s;
     anInvocation.selector = @selector(tell1111);
     [anInvocation invoke];
}

解析

  • methodSignatureForSelector 方法主要是返回对应的方法签名
  • forwardInvocation 主要是设置方法的执行对象与方法的实现。

反汇编研究转发流程

准备

下载Hopper反汇编的工具(打开选择demo)
通过hopper 打开CoreFoundation的可执行文件,去查找__forwarding_prep_0___,CoreFoundation的可执行文件怎么获取

loc_649bb:
    stack[-336] = r13;
    stack[-320] = r12;
    stack[-352] = rsi;
    rax = object_getClass(rbx);
    r12 = rax;
    r13 = class_getName(rax);
    if (class_respondsToSelector(r12, @selector(forwardingTargetForSelector:)) == 0x0) goto loc_64a67;

loc_649fc:
    rdi = rbx;
    rax = [rdi forwardingTargetForSelector:stack[-328]];
    if ((rax == 0x0) || (rax == rbx)) goto loc_64a67;

loc_64a19:

loc_64a8a:
    rax = class_respondsToSelector(r12, @selector(methodSignatureForSelector:));
    r14 = stack[-320];
    stack[-336] = r15;
    if (rax == 0x0) goto loc_64dd7;

loc_64ab2:
    rax = [r14 methodSignatureForSelector:stack[-328]];
    rbx = stack[-352];
    if (rax == 0x0) goto loc_64e3c;

loc_64ad5:

loc_64ad5:
    r12 = rax;
    rax = [rax _frameDescriptor];
    r13 = rax;
    if (((*(int16_t *)(*rax + 0x22) & 0xffff) >> 0x6 & 0x1) != rbx) {
            rax = sel_getName(stack[-328]);
            _CFLog(0x4, @"*** NSForwarding: warning: method signature and compiler disagree on struct-return-edness of '%s'.  Signature thinks it does%s return a struct, and compiler thinks it does%s.", rax);
    }
    rax = object_getClass(r14);
    rax = class_respondsToSelector(rax, @selector(_forwardStackInvocation:));
    stack[-344] = r13;
    if (rax == 0x0) goto loc_64c19;

loc_64b6c:

loc_64c19:
    if (class_respondsToSelector(object_getClass(r14), @selector(forwardInvocation:)) == 0x0) goto loc_64ec2;

loc_64c3b:
    rax = [NSInvocation _invocationWithMethodSignature:r12 frame:stack[-336]];
    r13 = rax;
    [r14 forwardInvocation:rax];
    stack[-328] = 0x0;
    r14 = 0x0;
    goto loc_64c76;

loc_64ec2:

结论

  • 快速转发:通过forwardingTargetForSelector实现,指定对象接收这个消息,就会走该对象的方法查找流程,如果返回nil,进入慢速转发流程
  • 慢速转发:通过methodSignatureForSelectorforwardInvocation共同实现,如果methodSignatureForSelector返回值是nil,慢速查找流程结束,如果有返回值forwardInvocation不会崩溃。
给定引用内容未提及MLAG(Multi - chassis Link Aggregation Group)的转发流程相关信息,以下是基于专业知识的介绍: MLAG转发流程主要包含以下几个关键阶段: ### 接收阶段 当流量进入MLAG系统时,流量会首先到达其中一台成员设备。成员设备会对接收的帧进行基本检查,如检查帧的格式、VLAN标签等是否合法。若帧格式不符合要求,该帧会被丢弃;若格式合法,则进入后续处理流程。 ### 本地转发决策 成员设备会根据帧的目的MAC地址和自身的MAC地址表进行匹配。若目的MAC地址在本地MAC地址表中存在,并且对应的端口为本地端口,设备会直接将帧从该本地端口转发出去。 ### MLAG同步与协商 如果目的MAC地址不在本地MAC地址表中,或者对应的端口为MLAG链路,设备会触发MLAG同步机制。成员设备之间通过专用的MLAG控制链路进行信息交互,同步MAC地址表、链路状态等信息。通过这种同步,两台成员设备能够保持一致的转发视图。 ### 跨设备转发 当需要跨设备转发流量时,成员设备会将帧通过MLAG链路转发到另一台成员设备。在MLAG链路中,流量会根据一定的负载均衡算法(如基于源MAC地址、目的MAC地址、IP地址等)进行分发,以充分利用链路带宽。 ### 目的端口转发 另一台成员设备接收到跨设备转发过来的帧后,会再次根据本地的MAC地址表进行查找。若找到对应的目的端口,设备会将帧从该端口转发出去,完成整个转发流程。 ```plaintext # 简单的MLAG转发流程示意伪代码 if frame_received: if frame_format_check(frame): mac_entry = lookup_mac_table(frame.destination_mac) if mac_entry and mac_entry.port is local_port: forward_frame(frame, mac_entry.port) else: sync_mac_table_with_peer() if mlag_link_needed: select_mlag_link(frame) forward_frame_over_mlag(frame) else: drop_frame(frame) else: drop_frame(frame) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值