找回密码
 立即注册
查看: 238|回复: 0

Android 网络浅析

[复制链接]
发表于 2022-5-12 16:54 | 显示全部楼层 |阅读模式
1、网络协议指的是什么


所谓协议,就是一种“规范”、或者说“约定”,在通俗点就是“某种规则”。 平时编程用到语言:java、c++、js等也属于协议。 协议一般包含三个要素:
    语法 按照某种规则。如谍战片中的加密电报语义 根据这种规则,需要表达的意思顺序 形成某种顺序,包含上下文信息 如 先干什么,然后在干什么等等

那么网络协议,就是应用在网络通信中的一种规范。平时常用到的网络协议有:
分层用到的协议
应用层DHCP(动态主机配置)、DNS(域名系统)、http(普通传输)、https(加密传输)
传输层TCP(面向连接) UDP(无连接协议)
网络层IP
链路层ARP
物理层网络跳线

详细解释: DHCP(动态主机配置): Dynamic Host Configuration Protocol 当设备启动联网后,DHCP负责给设备分配ip地址、默认网关的ip地址。
2、网络分层


网络有五层和七层之分,这里主要讨论五层。如上表所示。 分层可以让复杂问题简单化,每一层专注做自己的事情,层与层之间是有联系的。 发起一个网络请求,想要通过网络到达服务端,那么就需要根据每一层的网络协议去封装具体的请求数据(只有按照这种规则才能成功抵达目标服务器),到达目标服务器后,经过服务器的处理,返回的数据也同样需要经过每一层的网络协议包装,经由网络回到起点。在这样的一个过程中每一层都在什么?
2.1、每一层在都干什么


从网站买一本书为例:

发起侧(从上往下):
分层做了什么
应用层DNS(把服务器的域名解析为对应的ip地址->https/http(加上请求头的信息:json/protobuf格式,加上请求体body:我要买书)
传输层封装当前应用程序在本机上的端口,服务器程序的监听端口
网络层封装当前设备的ip地址,服务器ip地址
链路层封装当前设备ip对应的MAC地址,封装当前网关ip的MAC地址
物理层根据目标ip地址,网卡开始路由分发

接收侧(从下往上):
分层做了什么
应用层 5根据https/http规则进行解析,得到具体请求(我要买书)
传输层 4解析比较当前服务器的端口,与目标服务器程序的监听端口
网络层 3解析比较当前服务器ip地址与 目标服务器ip地址
链路层 2解析当前服务器ip对应的MAC地址,与传递过来的目标MAC地址比较
物理层 1到达目标服务器网关路由(如果这个包我可以拿过来)

注意:

本地网络内部是以MAC地址进行通信的,外地网络是以ip地址来通信的。两者通过网关(就是路由)连接起来。

MAC地址是网卡的唯一标识,类似身份证号码。

ip地址相当于身份证上的门牌地址。 只有知道门牌号+身份证号才能在网络世界中找到你。

MAC: Medium Access Control 媒体访问控制

路由器是一个网络设备,包含多张网卡。当一个网络包进来,路由会根据路由表来进行处理。而路由表一般包含如下规则:
    这个包的目标地址?将包该从哪个端口发出?下一跳路由网关:下一个路由地址是?

解包的具体流程:

当网络包从网口经过的时候,这里会根据设置的模式来看看这个包是不是需要我来处理下。 拿包进来后,交给layer2层来处理。从数据包中拆下mac头,看看mac头协议我需要做什么。 若mac匹配则交给lyaer3层,否则就转发出去。从包中拆下ip头,根据ip头协议是不是要做什么处理。 若ip匹配则交给layer4层,否则就转发出去。传输层会根据地址来区分,如果是发给tcp的则调用process_tcp来处理。tcp会根据tcp头来判断这是一个发起、还是一个应答、还是一个普通的数据,分不同的逻辑来处理。 处理完成后,在根据应用程序监听的端口来发给具体的应用程序(如web浏览器、手机端的app)。注意,这里不会有再交给http层的概念了。

问题:

1,tcp三次握手的时候,应用层是如何参与?网络层和物理层是如何工作的?

tcp握手时候,应用层是没有参与的。而tcp每发送一个消息,都会带上ip层和mac层。因此,握手过程不除了tcp层,ip层和mac层都在默默辛苦的工作。

每一个在网络上的包,都是完整的。可以没有上层,不能没有下层。

2,二层设备、三层设备指的什么?

所谓的二层、三层设备其实指的是在设备跑的程序不同而已。 因为只要到达了二层,那么这个包就是完整的。如果只拆mac,那么就是二层设备。 如果再拆ip头,那么就是三层设备。
3、TCP/UDP

3.1,TCP与UDP的区别?


TCP是面向连接的,而UDP是面向无连接。
    TCP在互通之前,需要进行三次握手建立连接。它是可靠的传输,保证顺序。具有拥塞机制,当网络不好或者意识到丢包情况,会自动减少数据包的发送。面向字节流的,以流为单位发送,没有说明什么时候关闭,除非显示关闭(断开连接)。ip包是没有流概念的,流是TCP本身维护的状态一个有状态的服务,发送了没有?接收了没有?改接收哪个了?等等

UDP继承了ip包特性:
    是不可靠的传输。一经发出,不保证不丢失,不保证顺序。无状态。无脑发送。基于数据报,一个一个发送。

mac层叫帧-frame,网络层叫包-package,传输层叫段-segment。统称为包。
3.2,UDP的头是啥样的?


网络层拆解ip头后,里面有一个8位的协议指明了是TCP包还是UDP包,也就是要交给TCP还是UDP来处理。

当传输层拿到UDP头后,里面包含了源应用的端口号和目标应用的端口号。不管是TCP还是UDP都会监听端口号,因此在系统中,端口号是唯一的,一个端口对应一个应用。

UDP的特点就是,沟通传输简单。发数据的时候只管发,不管网络如何,也不管对方是否能接收到。 接收的时候,因为没有连接,只管接收,不管是谁发的我都收。因此,UDP可实现一对多发送。不用一对一建立连接。

在语音和视频直播场景,DHCP配置场景都有UDP的应用。
3.3,TCP

3.3.1 TCP的包头


既然TCP相比UDP,包头复杂很多。包含如下方面:
    源端口地址和目标端口地址序号 解决包的乱序问题,不管是发送还是接收都有顺序确认序号 解决丢包问题。发出去的包必须受到回包,否则会重新发送。状态机 维护连接状态。随着通信双方状态的变化,tcp的连接状态也会随着更新:从建立连接到关闭连接。窗口大小 流量大小控制。表明能够处理数据多少的能力。不能太快也不能太慢。拥塞机制 网络环境不好时,会自动调整发送速度

注:

TCP无法控制网络环境,只能通过算法在TCP层尽可能的保证可靠。
3.3.2 TCP的三次握手


三次握手的目的是什么?

三次握手做了两件事情:

1,通过发送包、接收包,客户端和服务端各自维护了状态,建立连接。

根据状态机的变化来表示断开开始连接状态。其实本质上网络是不存在状态的,这只是tcp与服务端各自逻辑的实现。

2,确定本次连接数据包的序号 ISN(Initial Sequence Number)

避免网络延迟导致的多次连接后包序混乱。ISN是动态生成。

握手的过程:

简要描述:
    你好,我是A。你好A,我是B。你好 B。

详细描述:
    服务端处于监听状态listen客户端发起握手请求(你好,我想要连接了哦),状态变为syn_sent服务端收到请求后随后发起应答请求(你好,可以的),状态变为syn_received客户端收到请求返回的ack,随后回复服务端(应答的应答:嗯,好的。),状态变为established服务端收到客户端应答,状态变为established

问题:
    为什么是三次握手,不是两次或者四次?三次握手可以携带数据吗?半连接是什么?SYN攻击是什么?

1,为什么是三次握手,不是两次或者四次?

两次: 客户端发起请求,服务端返回。客户端可以确认服务端ok,但是服务端没有收到客户端确认ack,没法确定客户端ok。

四次:经过三次握手,其实可认为双方都已经确认ok。如果不能确认,就算四次握手,十次握手也不能确定。

2,三次握手可以携带数据吗?半连接是什么? SYN攻击是什么?

前两次握手是不能携带数据的。因为服务端在收到syn后,已经进入半连接状态,会将该链接放入半连接队列里面,此时开始分配资源和内存。而如果存在大量的非法连接请求,携带大量数据(根本不用等服务端返回)。会造成服务端大量资源被占用无法释放。

第三次握手是可以携带数据的。
3.3.3 TCP的四次挥手


到了说再见的时候了。

简要流程:
    客户端:服务端,我想断开了服务端:好的,客户端服务端:客户端,我也想断开了客户端:好的,服务端

详细流程: 当①②走完后,此时如果服务端不在发送③步,那么系统内核会根据一个超时时间来关闭该连接。

当③④走完后,客户端不会立即计入closed状态,而是进入time_wait。

有两个原因:
    需要等到报文在网络的最大存活时间,让第④步到达服务端。有可能服务端没收到,那么会重新发送FIN到客户端。还需要等待接收服务端一些延时到达的数据包

在等待2MSL(max segment life,一般为30s、1、2分钟)后,无论如何,客户端都会关闭了。tcp基于ip,ip中有TTL(time to life)域就是网络包的存活时间。
3.3.4 TCP的应答方式


tcp并不是发起一个请求,必须等到该请求的应答返回才去发送下一个。这样效率太低了。

累计确认/累计应答:

发送端会一次发送多个包,然后等待接收端的应答一起确认。 当然,发送端不能无限制的发送,接收端也不可能无限制接收,所以就有了发送窗口和接收窗口。
3.3.5 TCP的滑动窗口


发送端窗口:
    发送且已经确认 已处理,此时不算入窗口内发送待确认 在窗口内未发送可以发送 在窗口内不可发送 不在窗口内

接收端窗口:
    接收已确认 尚未被应用程序消费,在窗口内,带接收 在窗口内不可接收 不在窗口内

滑动窗口原理:

注意: 滑动窗口是一种控制流量的方式。 发送端的窗口大小是有接收端来决定的。

从三次握手到中间的数据传输,接收端都会通过ack告诉发送端,接收端窗口的大小(也就是能处理数据包多少的能力)。

想象发送端的数据包都在一个队列里面(都已经编号),只要接收端返回ACK通知哪个包已经被成功接收,那么发送端就会确认改包。从而发送端窗口就会往右边移动,至于移动多少呢? 这就跟接收端能接收多少有关了(接收窗口)。 发送端可用窗口大小=接收端窗口-发送尚未确认的包段大小

如果程序一直没有处理包,当接收端窗口满了的时候,那么可用窗口就=0。那么此时发送端不会再发送数据。

但是会有零窗口机制,发送端会去探测接收端是否有空窗口使用。如果有则继续发送。

滑动窗口示意图:

4、socket套接字


socket是对tcp和udp的再一次封装。 应用层只需要通过socket就能完成网络连接(不用关心三次握手、四次挥手的具体的操作)。

更高层次理解:

socket是实现端对端的通信。中间经过多少网络、路由器它都不知道。因此,它只能设置网络层和传输层的参数:
    网络层:设置ip。是ip4还是ip6传输层:除了设置端口号,是tcp还是udp。 tcp基于数据流,因此是SOCKET_STREAM, udp基于数据报传输,是SOCKET_DGRAM。
4.1 基于tcp的socket调用过程

    服务端创建监听socket,调用bind()函数为socket绑定ip和端口。服务端调用socket的 listen函数,进入listen状态服务端调用socket的 accept函数,如果有连接则会返回,如果没有则阻塞,直到客户端发起连接。注意 此时发回的已连接socket与上面监听的socket是两个对象。客户端通过创建、bind socket后,发起连接connect函数(通过三次握手)服务端accept收到,在服务端返回一个新的socket对象。至此,客户端与服务端可以通过socket来 读、写数据了

文件描述符

每一个进程会有一个数组用来保存所访问的过文件,而文件描述符fd则是这个数组的下标。fd是一个整数。
4.2 基于udp的socket调用过程


udp不需要建立连接,所以不会有三次握手。

服务端不用为每个连接维护一个socket,而是只要一个socket即可实现一对多的通信。 一个服务端socket 对应 多个客户端。

调动过程:
    服务端创建socket,调用bind函数绑定ip和端口。客户端创建socket,调用bind函数。直接调用sendTo发送数据到服务端服务端调用recvFrom接收数据

4.3 服务端是如何做到维护大量tcp连接的?


基本原理: 需要用到 多进程、多线程

通过epoll机制(基于红黑树)回调 来解决C10K 的问题。

一个线程可以维护多个socket连接。 socket在内核中相当打开了文件,也就对应一个文件描述符。利用epoll机制,注册callback(而非轮询),只要socket对应的文件描述符有变化,那么就会主动回调到处理线程。那么线程就能处理了。

当然还要多进程方式。 通过fork一个子进程来处理。
5、http与https

5.1 http

5.1.1 http请求前准备


在构建完http请求后,不是直接就开始发送的。而是要先建立tcp连接,经过三次握手后,经由socket才到传输层去发送请求。
5.1.2 http的请求构成


http请求分为:
    请求行 包含方法、url、http版本请求头 key-value值 如keep-alive请求体 正文内容

1,请求行

get方法是从服务端获取某种资源。 post方法则是告诉服务端一些信息。如:我要买什么,卖多少等

2,请求头中 缓存:

客户端访问一些不会经常变动的资源(静态资源),一般会有缓存。服务端首先会判断处于缓存期间,且该资源没有变动。则直接返回缓存。否则,会访问最新服务器拉取资源。
5.1.3 http的响应构成


http响应:
    响应行 返回状态码响应头 key-value响应体 返回的内容
5.1.4 http1.1 与http2.0的区别


http1.1之前,如果有多个请求是串行执行请求的。 即:请求1-返回1-请求2-返回2-请求3-返回3。

http2.0后,会把三个请求同时发送和返回,通过把多个请求分散到多个流中,并且每个请求的数据在tcp层切分为帧,每个镇是会被打乱传输。这样就解决阻塞问题。

头压缩,通过在双端建立索引表。把公共的key-value,只穿索引号,减少头部空间。

另外,也不需要http1.x中的通过pipleline机制维护的多个tcp连接,来实现并行请求。
5.1.5 google的QUIC


google 基于udp实现了类似于tcp一样的连接、多路复用、重试、流量控制等协议。
5.2 https


https是建立在tls套件之上的http,加密传输。 利用非对称加密用来验证证书的安全性、合法性,在通过对称加密来进行数据传输。
5.2.1 SSL 与 TLS

    SSL: secure socket layer。安全套阶层TLS:transport layer security 传输层安全协议。 用来替换SSL加密套件。
5.2.2 对称加密与非对称加密


对称加密:发送方和接收方都是同一个把密钥。特点是加密效率高。密钥容易泄露,不安全。 非对称加密: 发送方自己保留私钥,用私钥进行加密,接收方(可能有多个)用公钥进行解密。特点加密慢。

因此一般采用组合方式: 对称加密的私钥 通过非对称加密来传输。
5.2.3 CA证书


证书里面包含了 公钥、证书的申请者、发布者、日期、有效日期等信息。

第三方公司的公钥不能直接放到网站上让app自己去下。 这样不可靠。而是通过生成证书的方式来对外部调用者提供。

因此,我只要能证明第三方公司的CA合法,那也就认为它的公钥合法。为了给第三方公司的证书作证明,需要权威CA机构来给第三方公司的证书做签名保证(如:这个身份证是派出所签了名的啊,是合法的。)。

因此,我们需要证明该CA机构合法(我要证明派出所是合法的。 这是一个不断CA的过程,直到顶层CA,如国务院颁发的? 哦,那就没问题了),这个过程一般是从系统自带的CA库中去查找。再用该机构的公钥去解密改机构的签名保证,从而认为第三方公司的证书合法,最终认为第三方公司的公钥合法。

然后我们利用公钥和一些随机数规则来生成会话用的对称加密私钥。有了私钥就可以安全、愉快的进行数据传输了。
5.2.4 https的加密过程


前提: 所有的加密操作都是建立在tcp建立连接以后。
    c-->s: 我使用https加密传输,我的加密套件是tls版本xxx等信息,给你一个随机数。s-->c: 我也使用https,我的加密条件是tls版本xx等信息 ,也给你一个随机数。s-->c:这是我的证书xx,你验证下吧c:通过ca验证证书可靠。拿到公钥。在生成一个pre-master随机数,通过公钥传给s。c-->s: 计算得到私钥(自己的随机数+对端的随机数+pre-master随机数),我们以后就用这个私钥传输吧。c-->s: 利用私钥测试下消息发送s-->c: 计算得到私钥,可以啊。我们以后就这样沟通了。

后面,就是http的传输过程了。
6、dns 与 httdns

    dns:

域名解析系统,即把域名解析成ip。 它首先会从本地系统的缓存中去读取,然后就近的dns服务器获取,最终去主域名服务器获取。每一层都有缓存。如果更新不及时就会引发ip更新不及时的问题。

缺点:
    缓存时间无法确定。设置过长导致ip更新不及时,设置过短导致命中不了缓存,从而请求时间增加。域名劫持 中间可能返回其他网站的ip,发生劫持。解析过长不可控,无法快速解析ip一次只能解析一个域名

    httpdns:

通过自己的服务器来管理域名与ip的对应关系。 app在启动的时候从后台拉取映射表数据到本地,然后通过跑马拿到最快的ip地址(或者服务端直接返回就近的ip地址),从而实现替换。

一次可以解析多个域名。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-27 08:29 , Processed in 0.187126 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表