网络协议(一)
网络协议(一)
简述 TCP 三次握手以及四次挥手的流程。为什么需要三次握手以及四次挥手?
三次握手
第一次握手
客户端给服务器发送一个SYN段(在 TCP 标头中 SYN 位字段为 1 的 TCP/IP 数据包), 该段中也包含客户端的初始序列号(Sequence number (Seq)= J)。
SYN是同步的缩写,SYN 段是发送到另一台计算机的 TCP 数据包,请求在它们之间建立连接
SYN = j , Seq = k
第二次握手
服务器返回客户端 SYN +ACK 段(在 TCP 标头中SYN和ACK位字段都为 1 的 TCP/IP 数据包), 该段中包含服务器的初始序列号(Sequence number(Seq) = K);同时使 Acknowledgment number = J + 1来表示确认已收到客户端的 SYN段(Sequence number = J)。ACK 是“确认”的缩写。 ACK 数据包是任何确认收到一条消息或一系列数据包的 TCP 数据包
SYN = j, Seq =y, ACK= k+1
第三次握手
客户端给服务器响应一个ACK段(在 TCP 标头中 ACK 位字段为 1 的 TCP/IP 数据包), 该段中使 Acknowledgment number = K + 1来表示确认已收到服务器的 SYN段(Sequence number(Seq) = K)。ACK= y+1
为什么三次?
第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
换个易于理解的视角来看为什么要 3 次握手。
客户端和服务端通信前要进行连接,“3次握手”的作用就是双方都能明确自己和对方的收、发能力是正常的。
四次挥手
- 客户端发送一个 FIN 段,并包含一个希望接收者看到的自己当前的序列号 K. 同时还包含一个 ACK 表示确认对方最近一次发过来的数据。
- 服务端将 K 值加 1 作为 ACK 序号值,表明收到了上一个包。这时上层的应用程序会被告知另一端发起了关闭操作,通常这将引起应用程序发起自己的关闭操作。
- 服务端发起自己的 FIN 段,ACK=K+1, Seq=L。
- 客户端确认。进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)后释放连接。ACK=L+1。
为什么关闭连接却是四次挥手?
TCP连接是双向传输的对等的模式,就是说双方都可以同时向对方发送或接收数据。当有一方要关闭连接时,会发送指令告知对方,我要关闭连接了。
这时对方会回一个ACK,此时一个方向的连接关闭。但是另一个方向仍然可以继续传输数据,也就是说,服务端收到客户端的 FIN 标志,知道客户端想要断开这次连接了,但是,我服务端,我还想发数据呢?我等到发送完了所有的数据后,会发送一个 FIN 段来关闭此方向上的连接。接收方发送 ACK确认关闭连接。
注意,接收到FIN报文的一方只能回复一个ACK, 它是无法马上返回对方一个FIN报文段的,因为结束数据传输的“指令”是上层应用层给出的,我只是一个“搬运工”,我无法了解“上层的意志”。
客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。
因为服务端在 LISTEN 状态下,收到建立连接请求的 SYN 报文后,把 ACK 和 SYN 放在一个报文里发送给客户端。而关闭连接时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方 ACK 和 FIN 一般都会分开发。
HTTP 与 HTTPS 有哪些区别?
1、HTTPS 协议需要到 CA (Certificate Authority,证书颁发机构)申请证书,一般免费证书较少,因而需要一定费用。(以前的网易官网是http,而网易邮箱是 https 。)
2、HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。
3、HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、HTTP 的连接很简单,是无状态的。HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。(无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。)
注意:
(1) 采用 HTTPS 协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问。这套证书其实就是一对公钥和私钥。
(2) 互联网有太多的服务需要使用证书来验证身份,以至于客户端(操作系统或浏览器等)无法内置所有证书,需要通过服务端将证书发送给客户端。
(3) 客户端内置的是 CA 的根证书(Root Certificate),HTTPS 协议中服务器会发送证书链(Certificate Chain)给客户端。
数据传输的机密性:包含自己支持的非对成加密的密钥交换算法 ( 一般是RSA),数据签名摘要算法 ( 一般是SHA或者MD5) ,加密传输数据的对称加密算法 ( 一般是DES),以及加密密钥的长度。
非对称加密公钥和私钥的使用方法:(1) 公钥加密私钥解密。(2) 私钥做数字签名,公钥验证。
从输入 URL 到展现页面的全过程
输入url地址
应用层进行DNS解析
应用层生成HTTP请求报文
传输层建立TCP连接
网络层使用IP协议来选择路线
数据链路层实现网络相邻节点间可靠的数据通信
物理层传输数据
服务器处理反向传输
服务器返回一个 HTTP 响应
浏览器渲染
TCP 与 UDP 在网络协议中的哪一层,他们之间有什么区别?
TCP与UDP都在传输层
用户数据报协议 UDP(User Datagram Protocol)
是无连接的,尽最大可能交付,没有拥塞控制,面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信。
传输控制协议 TCP(Transmission Control Protocol)
是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)。
TCP 怎么保证可靠传输?
TCP主要提供了检验和、序列号/确认应答、超时重传、最大消息长度、滑动窗口控制等方法实现了可靠性传输。
- 校验和:
发送的数据包的二进制相加然后取反,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。
- 确认应答+序列号(累计确认+seq):
接收方收到报文就会确认(累积确认:对所有按序接收的数据的确认)
TCP给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
- 超时重传:
当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
- 流量控制:
TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP使用的流量控制协议是可变大小的滑动窗口协议。
接收方有即时窗口(滑动窗口),随ACK报文发送
- 拥塞控制:
当网络拥塞时,减少数据的发送。
发送方有拥塞窗口,发送数据前比对接收方发过来的即使窗口,取小
简述 HTTP 1.0,1.1,2.0 的主要区别
HTTP1.0与HTTP 1.1的主要区别
- 长连接
- 节约带宽
- HOST域
缓存处理:在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
带宽优化及网络连接的使用:HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
错误通知的管理:在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
Host头处理:在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
长连接:HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
HTTP / 1.x与HTTP / 2区别
HTTP1.1与HTTP 2.0的主要区别
- 多路复用
- 二进制分帧
- 首部压缩
- 服务器推送
服务端推送:它引入了服务器推送的概念,其中服务器预计客户端将需要的资源,并在客户端发出请求之前将其推送。客户端保留拒绝服务器推送的权限;但是,在大多数情况下,此功能可大大提高流程效率。
多路复用:该概念交错了请求和响应,而没有行头阻塞,并且通过单个TCP连接来完成。
新的二进制格式:它是一种二进制协议,即仅以0和1形式的二进制命令通过网络传输。二进制成帧层将消息划分为多个帧,这些帧根据其类型(数据或报头)进行分离。此功能在安全性,压缩和多路复用方面大大提高了效率。
header压缩:HTTP / 2使用HPACK标头压缩算法,该算法可抵御像CRIME这样的攻击,并利用静态霍夫曼编码。
TCP 中常见的拥塞控制算法有哪些?
拥塞控制主要是四个算法:1)慢启动,2)拥塞避免,3)拥塞发生,4)快速恢复。
1.慢启动算法 - Slow Start
在 TCP 连接刚建立时,一点一点提速,先试探网络的状况,避免扰乱了网络通道的秩序。
慢启动是指一开始向网络注入的报文段少,并不是指拥塞窗口 cwnd 增长速度慢。
- 慢启动算法:
连接建好的开始先初始化拥塞窗口的 cwnd 大小为 1,表明可以传送一个 MSS 大小的数据。
每当收到一个 ACK,cwnd 大小加 1,呈线性上升。
每当过了一个往返延迟时间 RTT(Round-Trip TIme),cwnd 大小直接翻倍,乘以 2,呈指数上升。
还有一个 ssthresh(slow start threshold),是一个上限(阈值),当 cwnd >= ssthresh 时就会进入“拥塞避免算法”。
2. 拥塞避免算法- Congestion Avoidance
当窗口大小 cwnd >= 慢启动的阈值后,就会进入拥塞避免算法。
拥塞避免 不能完全避免拥塞,而是指在拥塞避免阶段将拥塞窗口控制为线性增长,避免窗口增长过快导致窗口拥塞。缓慢的增加调整到最佳状态,使网络比较不容易出现拥塞。
- 拥塞避免算法:
- 收到一个 ACK,则 cwnd = cwnd + 1/cwnd
- 每当经过了一个往返延迟时间 RTT,cwnd 大小加 1。
3.拥塞状态时的算法
TCP 拥塞控制默认认为网络丢包是由于网络拥塞导致的,所以一般的 TCP 拥塞控制算法以丢包为网络进入拥塞状态的信号。对于丢包有两种判断方式,一种是超时重传 RTO(Retransmission Timeout)超时,另一个是收到三个重复确认 ACK。
- 超时重传 RTO(Retransmission Timeout)超时,TCP 会重传数据包。TCP 认为这种情况比较糟糕,反应也比较激烈:
- 由于发生丢包,将慢启动阈值(ssthresh)设置为当前 cwnd 的一半,即 ssthresh = cwnd / 2
- cwnd 重置为 1
- 进入慢启动过程
早期的 TCP Tahoe 算法就是使用上述处理方法,由于一丢包就一切重来,导致 cwnd 又重置为 1,十分不利于网络数据的稳定传递。
所以,TCP Reno 算法进行了优化。当收到三个重复确认 ACK 时,TCP 开启快速重传 Fast Retransmit 算法,而不用等到 RTO 超时再进行重传
- 三个重复确认 ACK:
- cwnd 大小缩减为当前的一半。
- ssthresh 设置为缩小后的 cwnd 大小
- 进入快速恢复算法 Fast Recovery。
4.快速恢复算法 - Fast Recovery
TCP Tahoe 是早期的算法,所以没有快速恢复算法,而 Reno 算法有。在进入快速恢复之前,cwnd 和 ssthresh 已经被改为原有的 cwnd 的一半。
- cwnd = cwnd + 3 MSS,加 3 MSS 的原因是收到 3 个重复的 ACK。
- 重传 DACKs 指定数据包。
- 如果再收到 DACKs,那么 cwnd 大小增加 1。
- 如果收到新的 ACK,表明重传的包成功了,退出快速恢复算法。将 cwnd 设置为 ssthresh,然后进入拥塞避免算法。
什么是 TCP 粘包和拆包?
假设 Client 向 Server 连续发送了两个数据包,用 packet1 和 packet2 来表示,那么服务端收到的数据可以分为三种情况,现列举如下:
第一种情况,接收端正常收到两个数据包,即没有发生拆包和粘包的现象。
第二种情况,接收端只收到一个数据包,但是这一个数据包中包含了发送端发送的两个数据包的信息,这种现象即为粘包。这种情况由于接收端不知道这两个数据包的界限,所以对于接收端来说很难处理。
第三种情况,这种情况有两种表现形式,如下图。接收端收到了两个数据包,但是这两个数据包要么是不完整的,要么就是多出来一块,这种情况即发生了拆包和粘包。这两种情况如果不加特殊处理,对于接收端同样是不好处理的。
补充
TIME_WAIT
客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:
- 确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
- 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。
计网七层模型
OSI七层模型 | TCP/IP模型 | 功能 | TCP/IP协议族 |
---|---|---|---|
应用层 | 应用层 | 直接向用户提供服务,完成用户希望完成的各种网络操作 | HTTP,FTP,TFTP,DNS,Telnet,SMTP |
表示层 | 进行数据编解码,数据加解密和格式转换 | 没有协议 | |
会话层 | 解除或建立与别的节点的联系,组织和协调两个会话进程之间的通信,并对数据交换进行管理 | 没有协议 | |
传输层 | 传输层 | 向两台主机中进程之间的通信提供通用的数据传输服务,实现端到端连接 | TCP,UDP |
网络层 | 网络层 | 为分组交换网上的不同主机提供通信服务,也就是进行IP选址和路由选择 | IP,ICMP,RIP,IGMP |
数据链路层 | 数据链路层 | 在物理层提供的比特流基础上,通过差错控制、流量控制的方法,将由差错的物理线路变为无差错的、能可靠传输数据帧的数据链路 | SLIP,CSLIP,PPP,ARP,RARP, |
物理层 | 物理层 | 利用传输介质为数据链路层提供物理连接,实现相邻计算机节点之间比特流的透明传输 | IEEE802.1 A,IEEE802.2到IEEE802.11 |
UDP 、TCP 首部格式
TCP协议首部格式
TCP 首部格式比 UDP 复杂。
序号:用于对字节流进行编号,例如序号为 301,表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的序号应为 401。
确认号:期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701。
数据偏移:指的是数据部分距离报文段起始处的偏移量,实际上指的是首部的长度。
控制位:八位从左到右分别是 CWR,ECE,URG,ACK,PSH,RST,SYN,FIN。
CWR:CWR 标志与后面的 ECE 标志都用于 IP 首部的 ECN 字段,ECE 标志为 1 时,则通知对方已将拥塞窗口缩小;
ECE:若其值为 1 则会通知对方,从对方到这边的网络有阻塞。在收到数据包的 IP 首部中 ECN 为 1 时将 TCP 首部中的 ECE 设为 1;
URG:该位设为 1,表示包中有需要紧急处理的数据,对于需要紧急处理的数据,与后面的紧急指针有关;
ACK:该位设为 1,确认应答的字段有效,TCP规定除了最初建立连接时的 SYN 包之外该位必须设为 1;
PSH:该位设为 1,表示需要将收到的数据立刻传给上层应用协议,若设为 0,则先将数据进行缓存;
RST:该位设为 1,表示 TCP 连接出现异常必须强制断开连接;
SYN:用于建立连接,该位设为 1,表示希望建立连接,并在其序列号的字段进行序列号初值设定;
FIN:该位设为 1,表示今后不再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位置为 1 的 TCP 段。
每个主机又对对方的 FIN 包进行确认应答之后可以断开连接。不过,主机收到 FIN 设置为 1 的 TCP 段之后不必马上回复一个 FIN 包,而是可以等到缓冲区中的所有数据都因为已成功发送而被自动删除之后再发 FIN 包;
窗口:窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。
UDP协议首部格式
UDP首部有8个字节,由4个字段构成,每个字段都是两个字节,
1.源端口号: 可有可无,需要对方回信时选用,不需要时全部置0。
2.目的端口号:必须有,在终点交付报文的时候需要用到。
3.长度:UDP的数据报的长度(包括首部和数据)其最小值为8字节(只有首部)。
4.校验和:检测UDP数据报在传输中是否有错,有错则丢弃。
该字段是可选的,当源主机不想计算校验和,则直接令该字段全为0。
当传输层从IP层收到UDP数据报时,就根据首部中的目的端口,把UDP数据报通过相应的端口,上交给应用进程。
如果接收方UDP发现收到的报文中的目的端口号不正确(不存在对应端口号的应用进程0,),就丢弃该报文,并由ICMP发送“端口不可达”差错报文给对方。
为什么常说 TCP 有粘包和拆包的问题而不说 UDP ?
UDP 是基于报文发送的,UDP首部采用了 16bit 来指示 UDP 数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。
而 TCP 是基于字节流的,虽然应用层和 TCP 传输层之间的数据交互是大小不等的数据块,但是 TCP 并没有把这些数据块区分边界,仅仅是一连串没有结构的字节流;另外从 TCP 的帧结构也可以看出,在 TCP 的首部没有表示数据长度的字段,基于上面两点,在使用 TCP 传输数据时,才有粘包或者拆包现象发生的可能。
为什么会发生 TCP 粘包、拆包?
- 要发送的数据大于 TCP 发送缓冲区剩余空间大小,将会发生拆包。
- 待发送数据大于 MSS(最大报文长度),TCP 在传输前将进行拆包。
- 要发送的数据小于 TCP 发送缓冲区的大小,TCP 将多次写入缓冲区的数据一次发送出去,将会发生粘包。
- 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。
粘包、拆包解决办法
由于 TCP 本身是面向字节流的,无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决,根据业界的主流协议的解决方案,归纳如下:
- 消息定长:发送端将每个数据包封装为固定长度(不够的可以通过补 0 填充),这样接收端每次接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
- 设置消息边界:服务端从网络流中按消息边界分离出消息内容。在包尾增加回车换行符进行分割,例如 FTP 协议。
- 将消息分为消息头和消息体:消息头中包含表示消息总长度(或者消息体长度)的字段。
- 更复杂的应用层协议比如 Netty 中实现的一些协议都对粘包、拆包做了很好的处理。
TCP 滑动窗口
窗口是缓存的一部分,用来暂时存放字节流。发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小。
发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。
接收窗口只会对窗口内最后一个按序到达的字节进行确认,例如接收窗口已经收到的字节为 {31, 34, 35},其中 {31} 按序到达,而 {34, 35} 就不是,因此只对字节 31 进行确认。发送方得到一个字节的确认之后,就知道这个字节之前的所有字节都已经被接收。
题目答案均为转载,题目先后顺序按各大厂总出题次数排列!