导航:首页 > 源码编译 > 解析源码搜索名称

解析源码搜索名称

发布时间:2023-05-10 05:01:10

㈠ Android socket源码解析(三)socket的connect源码解析

上一篇文章着重的聊了socket服务端的bind,listen,accpet的逻辑。本文来着重聊聊connect都做了什么?

如果遇到什么问题,可以来本文 https://www.jianshu.com/p/da6089fdcfe1 下讨论

当服务端一切都准备好了。客户端就会尝试的通过 connect 系统调用,尝试的和服务端建立远程连接。

首先校验当前socket中是否有正确的目标地址。然后获取IP地址和端口调用 connectToAddress 。

在这个方法中,能看到有一个 NetHooks 跟踪socket的调用,也能看到 BlockGuard 跟踪了socket的connect调用。因此可以hook这两个地方跟踪socket,不过很少用就是了。

核心方法是 socketConnect 方法,这个方法就是调用 IoBridge.connect 方法。同理也会调用到jni中。

能看到也是调用了 connect 系统调用。

文件:/ net / ipv4 / af_inet.c

在这个方法中做的事情如下:

注意 sk_prot 所指向的方法是, tcp_prot 中 connect 所指向的方法,也就是指 tcp_v4_connect .

文件:/ net / ipv4 / tcp_ipv4.c

本质上核心任务有三件:

想要能够理解下文内容,先要明白什么是路由表。

路由表分为两大类:

每个路由器都有一个路由表(RIB)和转发表 (fib表),路由表用于决策路由,转发表决策转发分组。下文会接触到这两种表。

这两个表有什么区别呢?

网上虽然给了如下的定义:

但实际上在Linux 3.8.1中并没有明确的区分。整个路由相关的逻辑都是使用了fib转发表承担的。

先来看看几个和FIB转发表相关的核心结构体:

熟悉Linux命令朋友一定就能认出这里面大部分的字段都可以通过route命令查找到。

命令执行结果如下:

在这route命令结果的字段实际上都对应上了结构体中的字段含义:

知道路由表的的内容后。再来FIB转发表的内容。实际上从下面的源码其实可以得知,路由表的获取,实际上是先从fib转发表的路由字典树获取到后在同感加工获得路由表对象。

转发表的内容就更加简单

还记得在之前总结的ip地址的结构吗?

需要进行一次tcp的通信,意味着需要把ip报文准备好。因此需要决定源ip地址和目标IP地址。目标ip地址在之前通过netd查询到了,此时需要得到本地发送的源ip地址。

然而在实际情况下,往往是面对如下这么情况:公网一个对外的ip地址,而内网会被映射成多个不同内网的ip地址。而这个过程就是通过DDNS动态的在内存中进行更新。

因此 ip_route_connect 实际上就是选择一个缓存好的,通过DDNS设置好的内网ip地址并找到作为结果返回,将会在之后发送包的时候填入这些存在结果信息。而查询内网ip地址的过程,可以成为RTNetLink。

在Linux中有一个常用的命令 ifconfig 也可以实现类似增加一个内网ip地址的功能:

比如说为网卡eth0增加一个IPV6的地址。而这个过程实际上就是调用了devinet内核模块设定好的添加新ip地址方式,并在回调中把该ip地址刷新到内存中。

注意 devinet 和 RTNetLink 严格来说不是一个存在同一个模块。虽然都是使用 rtnl_register 注册方法到rtnl模块中:

文件:/ net / ipv4 / devinet.c

文件:/ net / ipv4 / route.c

实际上整个route模块,是跟着ipv4 内核模块一起初始化好的。能看到其中就根据不同的rtnl操作符号注册了对应不同的方法。

整个DDNS的工作流程大体如下:

当然,在tcp三次握手执行之前,需要得到当前的源地址,那么就需要通过rtnl进行查询内存中分配的ip。

文件:/ include / net / route.h

这个方法核心就是 __ip_route_output_key .当目的地址或者源地址有其一为空,则会调用 __ip_route_output_key 填充ip地址。目的地址为空说明可能是在回环链路中通信,如果源地址为空,那个说明可能往目的地址通信需要填充本地被DDNS分配好的内网地址。

在这个方法中核心还是调用了 flowi4_init_output 进行flowi4结构体的初始化。

文件:/ include / net / flow.h

能看到这个过程把数据中的源地址,目的地址,源地址端口和目的地址端口,协议类型等数据给记录下来,之后内网ip地址的查询与更新就会频繁的和这个结构体进行交互。

能看到实际上 flowi4 是一个用于承载数据的临时结构体,包含了本次路由操作需要的数据。

执行的事务如下:

想要弄清楚ip路由表的核心逻辑,必须明白路由表的几个核心的数据结构。当然网上搜索到的和本文很可能大为不同。本文是基于LInux 内核3.1.8.之后的设计几乎都沿用这一套。

而内核将路由表进行大规模的重新设计,很大一部分的原因是网络环境日益庞大且复杂。需要全新的方式进行优化管理系统中的路由表。

下面是fib_table 路由表所涉及的数据结构:

依次从最外层的结构体介绍:

能看到路由表的存储实际上通过字典树的数据结构压缩实现的。但是和常见的字典树有点区别,这种特殊的字典树称为LC-trie 快速路由查找算法

这一篇文章对于快速路由查找算法的理解写的很不错: https://blog.csdn.net/dog250/article/details/6596046

首先理解字典树:字典树简单的来说,就是把一串数据化为二进制格式,根据左0,右1的方式构成的。

如图下所示:

这个过程用图来展示,就是沿着字典树路径不断向下读,比如依次读取abd节点就能得到00这个数字。依次读取abeh就能得到010这个数字。

说到底这种方式只是存储数据的一种方式。而使用数的好处就能很轻易的找到公共前缀,在字典树中找到公共最大子树,也就找到了公共前缀。

而LC-trie 则是在这之上做了压缩优化处理,想要理解这个算法,必须要明白在 tnode 中存在两个十分核心的数据:

这负责什么事情呢?下面就简单说说整个lc-trie的算法就能明白了。

当然先来看看方法 __ip_dev_find 是如何查找

文件:/ net / ipv4 / fib_trie.c

整个方法就是通过 tkey_extract_bits 生成tnode中对应的叶子节点所在index,从而通过 tnode_get_child_rcu 拿到tnode节点中index所对应的数组中获取叶下一级别的tnode或者叶子结点。

其中查找index最为核心方法如上,这个过程,先通过key左移动pos个位,再向右边移动(32 - bits)算法找到对应index。

在这里能对路由压缩算法有一定的理解即可,本文重点不在这里。当从路由树中找到了结果就返回 fib_result 结构体。

查询的结果最为核心的就是 fib_table 路由表,存储了真正的路由转发信息

文件:/ net / ipv4 / route.c

这个方法做的事情很简单,本质上就是想要找到这个路由的下一跳是哪里?

在这里面有一个核心的结构体名为 fib_nh_exception 。这个是指fib表中去往目的地址情况下最理想的下一跳的地址。

而这个结构体在上一个方法通过 find_exception 获得.遍历从 fib_result 获取到 fib_nh 结构体中的 nh_exceptions 链表。从这链表中找到一模一样的目的地址并返回得到的。

文件:/ net / ipv4 / tcp_output.c

㈡ 什么是域名的源码解析

域名(Domain Name),是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置,地理上的域名,指代有行政自主权的一个地方区域)。域名是一个IP地址上有“面具” 。一个域名的目的是便于记忆和沟通的一组服务器的地址(网站,电子邮件,FTP等)。域名作为力所能及难忘的互联网参与者的名称,世界上第一个注册的域名是在1985年1月注册的。

简单的说,IP地址不方便记忆,有一定意义的数字和字母更方便记忆。

㈢ 怎么在网页的源代码查找自己要的文字

可以用浏览器自带的搜索功能在网页源代码中查找自己要的文字。

1、右击需要查看源代码的页面,在展开的菜单中点击“查看网嫌念页源皮者键代码”按钮:

㈣ 怎么找到spring注解解析器的源码

下面用的是4.2.5的源码。

从这个文件开始看:META-INF/spring.handlers

文件里的内容是http://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler


MvcNamespaceHandler源码:

㈤ 工具如何查找源代码

为了显示带注释的源代码和带注释的反汇编代码,性能分析器和er_print实用程序对于运行实验的程序所使用的源代码文件和装入对象文件必须具有访问权限。
首先在实验的archives目录中查找装入对象文件。如果在该目录中未找到,则将使用与下面所述的源文件和对象文件相同的算法查找这些文件。
在大多数实验中,源文件和对象文件按照完整路径的格式记录。Java 源文件还具有一个软件包名称,其中列出文件的目录结构。如果在记录实验的同一系统上查看实验,则可以使用完整路径找到源文件和装入对象。当实验移到其他计算机或者在其他计算机上查看实验时,这些完整路径可能无法访问。
可以使用两个补充方法来查找源文件和对象文件:路径映射和搜索路径。如果在archives子目录中没有找到装入对象文件,可以使用相同的方法来查找这些文件。
可以设置路径映射和搜索路径,帮助工具查找实验中引用的文件。在分析器中,使用 "Set Data Preferences"(设置数据首选项)对话框的 "Pathmaps"(路径映射)标签设置路径映射,并使用 "Search Path"(搜索路径)标签设置搜索路径,如
设置数据表示选项
中所述。对于er_print实用程序,使用pathmap和setpath指令,如控制源文件搜索的命令中所述。
/a/b/c/sourcefile
,并且pathmap指令指定将/a/映射到/x/y/
,则可以在/x/y/b/c/sourcefile
中找到文件。如果pathmap指令将/a/b/c/映射到/x/
,则可以在/x/sourcefile
中找到文件。
如果通过路径映射找不到文件,则将使用搜索路径。搜索路径提供了一个要为具有指定基名的文件搜索的目录列表,在上面的示例中,指定的基名为sourcefile
。可以使用setpath命令设置搜索路径,并使用addpath命令向搜索路径附加一个目录。对于 Java 文件,将尝试软件包名称,然后再尝试基名。
使用搜索路径中的每个目录来构造尝试搜索的完整路径。对于 Java 源文件,将构造两个完整路径,一个用于基名,另一个用于软件包名称。工具会将路径映射应用于每个完整路径,如果没有映射路径指向文件,则将尝试下一个搜索路径目录。
如果在搜索路径中没有找到文件,并且没有映射前缀与原始完整路径匹配,则将尝试原始完整路径。如果有任何路径映射前缀与原始完整路径匹配,但没有找到文件,则不会尝试原始完整路径。
请注意,缺省搜索路径包含当前目录和实验目录,因此一个使源文件可访问的方法是将源文件复制到这些位置之一,或者在这些位置中放置指向源文件当前位置的符号链接。

㈥ Feign源码解析二

本文会基于Feign源码,看看Feign到底是怎么实现远程调用

上文中,我们的 user-service 服务需要调用远程的 order-service 服务完成一定的业务逻辑,而基本实现是order-service提供一个spi的jar包给user-service依赖,并且在user-service的启动类上添加了一个注解

这个注解就是@EnableFeignClients,接下来我们就从这个注解入手,一步一步解开Feign的神秘面纱

该注解类上的注释大概的意思就是:
扫描那些被声明为 Feign Clients (只要有 org.springframework.cloud.openfeign.FeignClient 注解修饰的接口都是Feign Clients接口)的接口

下面我们继续追踪源码,看看到底什么地方用到了这个注解
利用IDEA的查找调用链快捷键,可以发现在.class类型的文件中只有一个文件用到了这个注解

OK,下面主要就是看这个类做了什么

通过UML图我们发现该类分别实现了 ImportBeanDefinitionRegistrar , ResourceLoaderAware 以及 EnvironmentAware 接口
这三个接口均是spring-framework框架的spring-context模块下的接口,都是和spring上下文相关,具体作用下文会分析

总结下来就是利用这两个重要属性,一个获取应用配置属性,一个可以加载classpath下的文件,那么FeignClientsRegistrar持有这两个东西之后要做什么呢?

上面将bean配置类包装成 FeignClientSpecification ,注入到容器。该对象非常重要,包含FeignClient需要的 重试策略 , 超时策略 , 日志 等配置,如果某个FeignClient服务没有设置独立的配置类,则读取默认的配置,可以将这里注册的bean理解为整个应用中所有feign的默认配置

由于 FeignClientsRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,这里简单提下这个接口的作用
我们知道在spring框架中,我们如果想注册一个bean的话主要由两种方式:自动注册/手动注册

知道了 ImportBeanDefinitionRegistrar 接口的作用,下面就来看下 FeignClientsRegistrar 类是何时被加载实例化的

通过IDEA工具搜索引用链,发现该类是在注解@EnableFeignClients上被import进来的,文章开始的图片中有

这里提下@Import注解的作用

该注解仅有一个属性value,使用该注解表明导入一个或者多个@Configuration类,其作用和.xml文件中的<import>等效,其允许导入@Configuration类,ImportSelector接口/ImportBeanDefinitionRegistrar接口的实现,也同样可以导入一个普通的组件类

注意,如果是XML或非@Configuration的bean定义资源需要被导入的话,需要使用@ImportResource注解代替

这里我们导入的FeignClientsRegistrar类正是一个ImportBeanDefinitionRegistrar接口的实现

FeignClientsRegistrar重写了该接口的 registerBeanDefinitions 方法,该方法有两个参数注解元数据 metadata 和bean定义注册表 registry

该方法会由spring负责调用,继而注册所有标注为@FeignClient注解的bean定义

下面看registerBeanDefinitions方法中的第二个方法,在该方法中完成了所有@FeignClient注解接口的扫描工作,以及注册到spring中,注意这里注册bean的类型为 FeignClientFactoryBean ,下面细说

总结一下该方法,就是扫描@EnableFeignClients注解上指定的basePackage或clients值,获取所有@FeignClient注解标识的接口,然后将这些接口一一调用以下 两个重要方法 完成 注册configuration配置bean 和注册 FeignClient bean

断点位置相当重要

BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);

这里是利用了spring的代理工厂来生成代理类,即这里将所有的 feignClient的描述信息 BeanDefinition 设定为 FeignClientFactoryBean 类型,该类继承自FactoryBean,因此这是一个代理类,FactoryBean是一个工厂bean,用作创建代理bean,所以得出结论,feign将所有的 feignClient bean定义的类型包装成 FeignClientFactoryBean

最终其实就是存入了BeanFactory的beanDefinitionMap中

那么代理类什么时候会触发生成呢? 在spring 刷新容器时 ,会根据beanDefinition去实例化bean,如果beanDefinition的beanClass类型为代理bean,则会调用其 T getObject() throws Exception; 方法生成代理bean,而我们实际利用注入进来的FeignClient接口就是这些一个个代理类

这里有一个需要注意的点,也是开发中会遇到的一个 启动报错点
如果我们同时定义了两个不同名称的接口 (同一个包下/或依赖方指定全部扫描我们提供的 @FeignClient ),且这两个 @FeignClient 接口注解的 value/name/serviceId 值一样的话,依赖方拿到我们的提供的spi依赖,启动类上 @EnableFeignClients 注解扫描能同时扫描到这两个接口,就会 启动报错

原因就是Feign会为每个@FeignClient注解标识的接口都注册一个以serviceId/name/value为key,FeignClientSpecification类型的bean定义为value去spring注册bean定义,又默认不允许覆盖bean定义,所以报错

官方提示给出的解决方法要么改个@FeignClient注解的serviceId,name,value属性值,要么就开启spring允许bean定义覆写

至此我们知道利用在springboot的启动类上添加的@EnableFeignClients注解,该注解中import进来了一个手动注册bean的 FeignClientsRegistrar注册器 ,该注册器会由spring加载其 registerBeanDefinitions方法 ,由此来扫描所有@EnableFeignClients注解定义的basePackages包路径下的所有标注为@FeignClient注解的接口,并将其注册到spring的bean定义Map中,并实例化bean

下一篇博文中,我会分析为什么我们在调用(@Resource)这些由@FeignClient注解的bean的方法时会发起 远程调用

阅读全文

与解析源码搜索名称相关的资料

热点内容
如何在vps上搭建自己的代理服务器 浏览:742
nginxphp端口 浏览:403
内脏pdf 浏览:150
怎么看云服务器架构 浏览:85
我的世界国际服为什么登不进服务器 浏览:996
微盟程序员老婆 浏览:930
intellij创建java 浏览:110
java连接odbc 浏览:38
启动修复无法修复电脑命令提示符 浏览:359
手机编程是什么 浏览:98
山东移动程序员 浏览:163
苏州java程序员培训学校 浏览:477
单片机液晶驱动 浏览:854
魔拆app里能拆到什么 浏览:131
新预算法的立法理念 浏览:144
wdcpphp的路径 浏览:134
单片机p0口电阻 浏览:926
浏览器中调短信文件夹 浏览:594
五菱宏光空调压缩机 浏览:69
为什么app占用几百兆 浏览:680