本文主要是介绍Android面试中会问到的网络基础,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、前言
本篇主要针对网络知识进行一个梳理
二、知识点
2.1、网络分层
计算机的网络体系结构分为3种:
- OSI 体系结构:概念清楚、理念完整,但复杂且不实用;
- TCP / IP体系结构:含了一系列构成互联网基础的网络协议,是Internet的核心协议 & 被广泛应用于局域网 和 广域网
- 五层体系结构:融合了 OSI 与 TCP / IP的体系结构,目的是为了学习 和计算机原理
OSI 体系结构 | TCP / IP 体系结构 | 五层体系结构 | 网络协议 |
---|---|---|---|
应用层 | 应用层 | 应用层 | HTTP(超文本传输协议) HTTPS(超文本传输安全协议) FTP(文件传输协议) SMTP(简单邮件传输协议) DNS(域名服务) 等等 |
表示层 | |||
会话层 | |||
传输层 | 运输层 | 运输层 | TCP(传输控制协议) UDP(用户数据报协议) |
网络层 | 网际层 | 网络层 | IP(网际协议) ICMP(网络控制消息协议) IGMP(网络组管理协议) |
链路层 | 网络接口层 | 链路层 | 以太网 Wi-Fi 等等 |
物理层 | 物理层 |
2.2、IP协议
网际协议(英语:Internet Protocol,缩写为IP),又译互联网协议,是用于分组交换数据网络的一种协议。
IP是在TCP/IP协议族中网络层的主要协议,任务仅仅是根据源主机和目的主机的地址来传送数据。为此目的,IP定义了寻址方法和数据报的封装结构。第一个架构的主要版本,现在称为IPv4,仍然是最主要的互联网协议,尽管世界各地正在积极部署IPv6。IP协议的作用在于把各种数据包准确无误的传递给对方,其中两个重要的条件是IP地址和MAC地址(Media Access Control Address)。由于IP地址是稀有资源,不可能每个人都拥有一个IP地址,所以我们通常的IP地址是路由器给我们生成的IP地址,路由器里面会记录我们的MAC地址。而MAC地址是全球唯一的,除去人为因素外不可能重复。举一个现实生活中的例子,IP地址就如同是我们居住小区的地址,而MAC地址就是我们住的那栋楼那个房间那个人。
2.3、TCP协议
传输控制协议(英语:Transmission Control Protocol,缩写为TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP 协议被认为是稳定的协议,因为它有以下特点:
- 面向连接,“三次握手”
- 双向通信
- 保证数据按序发送,按序到达
- 超时重传
要使用 TCP 传输数据,必须先建立连接,传输完成后释放连接。分别对应常说的“三次握手”、“四次挥手”。TCP 的三次握手与四次挥手的示意图如下:
2.3.1 三次握手
第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RCVD状态;
第三次握手:客户端收到服务器的SYN+ACK报文段。然后将ACK设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
当客户端和服务器通过三次握手建立了TCP连接后,当数据传输完毕,断开连接时就需要进行TCP的四次挥手。
2.3.2 四次挥手
TCP 协议中,在通信结束后,需要断开连接,这需要通过四次挥手,客户端或服务器均可主动发起,主动的一方先断开,这里以客户端先断开为例:
第一次挥手:客户端设置Seq和ACK,向服务器端发送一个FIN报文段;此时,客户端进入FIN_WAIT_1状态;客户端表示没有数据要发送给服务器端了;
第二次挥手:服务器端收到了客户端发送的FIN报文段,向主机1回一个ACK报文段,ACK为Sequence Number加1;客户端进入FIN_WAIT_2状态;服务器告诉客户端,我“同意”你的关闭请求;
第三次挥手:服务器向客户端发送FIN报文段,请求关闭连接,同时服务器进入LAST_ACK状态;服务器告诉客户端,我也没啥数据要发给你了,请求断开。
第四次挥手:客户端收到服务器发送的FIN报文段,向服务器发送ACK报文段,然后客户端进入TIME_WAIT状态;服务器收到客户端的ACK报文段以后,就关闭连接;此时,客户端等待2MSL后依然没有收到回复,则证明服务端已正常关闭,那好,客户端也可以关闭连接了。
2.3.3 为什么要进行三次握手
三次握手的目的是为了防止已失效的连接请求报文段突然又传到了服务端,服务端以为要建立连接,造成资源浪费(无效连接)。发生场景是,客户端发送第一个建立连接的请求由于网络原因服务端一开始没有接收到,因此客户端发了第二个连接请求,这个请求成功,建立起了连接。但是第一个请求后来又到达服务端,如果没有第三次确认,服务端将多形成一个连接,造成资源浪费。
2.3.4 为什么要进行四次挥手
TCP 连接是全双工的,每一端都可以同时发送和接受数据,关闭的时候两端都要关闭各自两个方向的通道,总共相当于要关闭四个。断开连接时,分为两个阶段。一次是客户端通知服务器,告知自己不会再发送数据。注意,此时服务器仍可以发数据给客户端。第二次是服务器告知客户端自己不会再发送数据。要弄清楚的是,断开时,任意一方都可以主动断开,表明自己不再发送数据,但仍可接收数据。所以中间的FIN和ACK不能合并。另外每次断开连接需要FIN请求 + ACK,所以断开需要四次。以客户端发起关闭为例:
- 服务器读通道关闭
- 客户端写通道关闭
- 客户端读通道关闭
- 服务器写通道关闭
2.3.5 客户端为什么要等待 2MSL
MSL(Maximum Segment Life),是 TCP 对 TCP Segment 生存时间的限制。客户端在发出确认服务端关闭的 ACK 后,它没有办法知道对方是否收到这个消息,于是需要等待一段时间,如果服务端没有收到关闭的消息后会重新发出 FIN 报文,这样客户端就知道自己上条消息丢了,需要再发一次;如果等待的这段时间没有在收到 FIN 的重发报文,说明它的确已经收到断开的消息并且已经断开了。这个等待时间至少是:客户端的 timeout + FIN 的传输时间,为了保证可靠,采用更加保守的等待时间 2MSL。
- 确保连接可靠关闭,防止最后一个ACK的丢失。
- 避免套接字混淆(同一个端口对应多个socket)
2.4、UDP协议
用户数据报协议(英语:User Datagram Protocol,缩写为UDP),又称用户数据报文协议,是一个简单的面向数据报的传输层协议。UDP是一个不可靠的或者说无连接的协议,他有以下的特点:
- UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次
- UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,那么该数据报的长度将随数据一起传递给接收方。而 TCP 是一个字节流协议,没有任何(协议上的)记录边界。
- UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
- UDP 支持多播和广播。
UDP 协议没有 TCP 协议稳定,因为它不建立连接,也不按顺序发送,可能会出现丢包现象,使传输的数据出错。但是有得就有失,UDP 的效率更高,因为 UDP 头包含很少的字节,比 TCP 负载消耗少,同时也可以实现双向通信,不管消息送达的准确率,只负责无脑发送。UDP 服务于很多知名应用层协议,比如 NFS(网络文件系统)、SNMP(简单网络管理协议)。UDP 一般多用于 IP 电话、网络视频等容错率强的场景。
特性 | TCP | UDP |
---|---|---|
有无连接 | 有 | 无 |
数据有序性、完整性 | 有 | 无 |
效率高低 | 低 | 高 |
数据大小 | 无限制 | 每个数据包64K |
应用方面 | 可靠通信 | 不需要可靠通信 |
2.5、Socket协议、Socket实现长连接
Socket 作为应用层和传输层之间的桥梁,与之关系最大的两个协议就是传输层中的 TCP 和 UDP协议。
Socket 是对 TCP/IP 协议族的一种封装,是应用层与TCP/IP协议族通信的中间软件抽象层。TCP或者UDP的报文中,除了数据本身还包含了包的信息,比如目的地址和端口,包的源地址和端口,以及其他附加校验信息。从设计模式的角度看来,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
Socket 还可以认为是一种网络间不同计算机上的进程通信的一种方法,利用三元组(ip地址,协议,端口)就可以唯一标识网络中的进程,网络中的进程通信可以利用这个标志与其它进程进行交互。
Socket 起源于 Unix ,Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开(open) –> 读写(write/read) –> 关闭(close)”模式来进行操作。因此 Socket 也被处理为一种特殊的文件。
如图所示,Socket 被称为“套接字”,它把复杂的 TCP/IP 协议簇隐藏在背后,为用户提供简单的客户端到服务端接口,让我们感觉这边输入数据,那边就直接收到了数据,像一个“管道”一样。
2.5.1 Socket 的使用
Socket 的基本操作有以下几部分:
- 连接远程机器
- 发送数据
- 接收数据
- 关闭连接
- 绑定端口
- 监听到达数据
- 在绑定的端口上接受来自远程机器的连接
要实现客户端与服务端的通信,双方都需要实例化一个 Socket。在 Java 中,客户端可以实现上面的 1、2、3、4、,服务端实现 5、6、7。Java.net 中为我们提供了使用 TCP、UDP 通信的两种 Socket:
- ServerSocket:流套接字,TCP
- DatagramSocket:数据报套接字,UDP
2.5.2 使用 TCP 通信的 Socket 流程
服务端:
- 调用 ServerSocket(int port) 创建一个 ServerSocket,绑定到指定端口
- 调用 accept() 监听连接请求,如果客户端请求连接则接受,返回通信套接字
- 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发
- 关闭套接字
客户端:
- 调用 Socket() 创建一个流套接字,连接到服务端
- 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发
- 关闭套接字
2.5.3 使用 UDP 通信的 Socket 流程
服务端:
- 调用 DatagramSocket(int port) 创建一个数据报套接字,绑定到指定端口
- 调用 DatagramPacket(byte[] buf, int length) 建立一个字节数组,以接受 UDP 包
- 调用 DatagramSocket 的 receive() 接收 UDP 包
- 调用 DatagramSocket.send() 发送 UDP 包
- 关闭数据报套接字
客户端:
- 调用 DatagramSocket() 创建一个数据报套接字
- 调用 DatagramPacket(byte buf[], int offset, int length,InetAddress address, int port) 建立要发送的 UDP 包
- 调用 DatagramSocket 的 receive() 接收 UDP 包
- 调用 DatagramSocket.send() 发送 UDP 包
- 关闭数据报套接字
2.6、HTTP协议
HTTP(HyperText Transfer Protocol 超文本传输协议)是一个处于应用层的面对对象协议。URL(Uniform Resource Location 统一资源定位符)是常说的网页地址。Http协议的主要特点如下:
- 支持C/S(客户/服务器)模式
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、POST,每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
- 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
- 无连接:无连接的喊一声限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- 无状态:HTTP协议是无状态协议,无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续需要处理前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大;而另一方面,在服务器不需要先前信息时它的应答速度就较快。
HTTP报文:
- 请求报文
- 报文头部
- 请求行:包括请求方法类型:GET、POST等,请求地址,协议版本
- 请求头部字段
- 通用头部字段
- 实体头部字段
- 其他
- 报文主体:包括如POST中的请求参数、文件上传数据、邮件传输数据等内容
- 报文头部
- 响应报文
- 报文头部
- 状态行
- 响应头部字段
- 通用头部字段
- 实体头部字段
- 其他
- 报文主体:包括网页正文等内容
- 报文头部
根据上述内容,HTTP头部字段包括:
- 通用头部字段:请求报文、响应报文都会使用,包括Date、Connection、Cache-Control(作用是控制HTTP缓存机制)字段
- 请求头部字段:补充请求的附加内容、客户端信息、响应内容相关优先级等。有Accept、User-Agent、Host等字段
- 响应头部字段:补充响应的附加内容
- 实体头部字段:用来定义被传送资源的信息,既可用于请求也可用于响应。
HTTP状态码
状态码 | 含义 |
---|---|
1xx | 指示信息,收到请求,需要请求者继续执行操作 |
2xx | 请求成功,请求已被成功接收并处理 |
3xx | 重定向,要完成请求必须进行更进一步的操作 |
4xx | 客户端错误,请求有语法错误或请求无法实现 |
5xx | 服务器错误,服务器不能实现合法的请求 |
2.7、HTTPS协议
简单来说 HTTPS 是加密的 HTTP,HTTPS = HTTP + SSL/TLS。HTTPS使用SSL/TLS进行加密,这既是它的优点也是它的缺点,加密使HTTPS的安全性大大提高,但是加密的过程也导致通信过程中性能的下降。但总的来说用失去的一点点性能换来极高的安全性是非常值得的,苹果和谷歌也大力支持HTTPS的使用。
HTTPS的关键是加密过程,HTTPS中SSL/TLS加密的握手过程如下(以下的C代表Client客户端,S代表Server服务端):
- C告诉S:协议版本号,支持的加密方法,以及自己生成的随机数
- S确认加密方法,给C方松证书和自己产生的随机数
- C确认证书有效性,产生新的随机数,并使用数字证书中的公钥加密随机数,发送给S
- S使用对应的私钥解密得到C发过来的随机数
- C和S使用约定的加密方法,使用前面的三个随机数,生成对话密钥,然后用此密钥加密接下来的整个对话过程
总的来说,整个过程就是使用非对称加密算法交换“对话中要使用的对称加密算法的密钥”,然后使用对称加密算法进行对话。
注:加密算法分为两种:对称和非对称。
- 对称加密:对话双方使用同一密钥进行加密和解密。特性是速度快,但存在如何安全确认密钥的问题。
- 非对称加密:拥有两个密钥,公钥和私钥。公钥加密的内容只有私钥能够解密,私钥加密的内容只有公钥能够解密。C向S发送内容时使用S的公钥加密,这样就只有持有对应私钥的S能够解密。特性是安全,但速度慢。同时存在如何证明公钥是S的问题,因为可能有人从中间劫持,伪装S发送劫持人的公钥。为了解决这个问题,引入了数字证书来保证公钥的有效性。
SSL/TLS结合了两种加密算法的优点,利用非对称加密的安全来交换对称加密的密钥,然后利用对称加密的速度快来对这个会话进行加密。
2.8、一次连接的具体过程
- 输入网址 URL
- 域名解析(DNS):发送到DNS(域名服务器)获得域名对应的WEB服务器的IP地址。
- TCP三次握手,建立连接 :客户端与WEB服务器建立TCP(传输控制协议)连接。
- 发起请求:客户端向对应IP地址的WEB服务器发送相应的HTTP或HTTPS请求。
- 服务器响应请求,返回数据 : WEB服务器响应请求,返回指定的URL数据或错误信息;如果设定了重定向,则重定向到新的URL地址。
- 客户端处理数据
- 合适时刻四次握手,断开连接
DNS功能是将域名解析为IP地址。DNS解析过程如下:
- 查找浏览器缓存,是否有解析记录,没有则进入第二步
- 查找系统缓存,是否有解析记录,没有则进入第二步
- 给配置的DNS服务器(LDNS)发送请求,LDNS查找到则返回
- LDNS没有找到时会请求RootServer,返回一个顶级域名服务器
- LDNS请求顶级域名服务器,返回NameServer地址
- NameServer返回IP给LDNS,LDNS会进行缓存
- LDNS返回给用户
注:各级都会对IP的解析进行缓存,同时会根据各自的缓存策略对一些记录进行清理
2.9、GET、POST的区别
- GET请求可以被浏览器缓存,POST不可以
- POST安全一些,因为GET请求都在URL中,也会被浏览器保存记录;而POST请求可以放到Body中
- POST可以用RequestBody传输更多的数据,GET的数据量受到URL长度限制
- POST支持更多编码,且不对数据类型限制
- GET的目标功能是查询数据,POST的目标功能是修改数据,或者上传数据
这篇关于Android面试中会问到的网络基础的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!