一、OSI 7层模型、TCP/IP四层模型
-
各个层的协议
-
数据包说明
IP层传输单位是IP分组,属于点到点的传输;TCP层传输单位是TCP段,属于端到端的传输
二、TCP传输层协议
概念
- TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,其传输的单位是报文段。
特征
- 面向连接的传输层协议
- 端对端的传输
- 提供可靠的交互
- 面向字节流
- 全双工通信
如何保证可靠传输
- 确认和超时重传
- 数据和合理分片和排序
- 拥塞控制和流量控制
- 数据校验
TCP报文结构
TCP首部
- 源端口、目的端口:16位长。标识出远端和本地的端口号。
- 序列号:32位长。表明了发送的数据报的顺序,不一定从0开始。
- 确认号:32位长。希望收到的下一个数据报的序列号,表明到序列号N-1为止的所有数据已经正确收到。
- TCP协议数据报头长:4位长。表明TCP头中包含多少个32位字。
- 接下来的6位未用。
- 窗口大小:16位长。窗口大小字段表示在确认了字节之后还可以发送多少个字节。
- 校验和:16位长。是为了确保高可靠性而设置的。它校验头部、数据和伪TCP头部之和。
- 紧急指针:URG=1时才有意义。
TCP的最小字节是20个字节
TCP状态控制码
TCP:状态控制码(Code,Control Flag),占 6 比特,含义如下:
- URG:紧急比特(urgent),当 URG=1 时,表明紧急指针字段有效,代表该封包为紧急封包。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据), 且上图中的 Urgent Pointer 字段也会被启用。
- ACK:确认比特(Acknowledge)。只有当 ACK=1 时确认号字段才有效,代表这个封包为确认封包。当 ACK=0 时,确认号无效。
- PSH:(Push function)若为 1 时,代表要求对方立即传送缓冲区内的其他对应封包,而无需等缓冲满了才送。
- RST:复位比特(Reset),当 RST=1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
- SYN:同步比特(Synchronous),SYN 置为 1,就表示这是一个连接请求或连接接受报文,通常带有 SYN 标志的封包表示『主动』要连接到对方的意思。
- FIN:终止比特(Final),用来释放一个连接。当 FIN=1 时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
TCP黏包问题
原因:
本质:TCP是面向字节流的传输协议,意味传输的数据没有边界。所以可能会出现两个数据包黏在一起的情况。
- 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。
- 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。
- 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。
- 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。
解决方案:
- 发送定长包:发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
- 添加包首部:发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。
- 在数据包之间设置边界。如添加特殊符号 \r\n 标记。FTP 协议正是这么做的。但问题在于如果数据正文中也含有 \r\n,则会误判为消息的边界。
- 使用更复杂的传输协议。
TCP三次握手
【TCP 建立连接全过程解释】
- 客户端发送 SYN 给服务器,说明客户端请求建立连接;
- 服务端收到客户端发的 SYN,并回复 SYN+ACK 给客户端(同意建立连接);
- 客户端收到服务端的 SYN+ACK 后,回复 ACK 给服务端(表示客户端收到了服务端发的同意报文);
- 服务端收到客户端的 ACK,连接已建立,可以数据传输。
TCP 为什么要进行三次握手?
【答案一】因为信道不可靠,而 TCP 想在不可靠信道上建立可靠地传输,那么三次通信是理论上的最小值。(而 UDP 则不需建立可靠传输,因此 UDP 不需要三次握手。)
【答案二】因为双方都需要确认对方收到了自己发送的序列号,确认过程最少要进行三次通信。
【答案三】为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
TCP四次挥手释放连接
【TCP 释放连接全过程解释】
- 客户端发送 FIN 给服务器,说明客户端不必发送数据给服务器了(请求释放从客户端到服务器的连接);
- 服务器接收到客户端发的 FIN,并回复 ACK 给客户端(同意释放从客户端到服务器的连接);
- 客户端收到服务端回复的 ACK,此时从客户端到服务器的连接已释放(但服务端到客户端的连接还未释放,并且客户端还可以接收数据);
- 服务端继续发送之前没发完的数据给客户端;
- 服务端发送 FIN+ACK 给客户端,说明服务端发送完了数据(请求释放从服务端到客户端的连接,就算没收到客户端的回复,过段时间也会自动释放);
- 客户端收到服务端的 FIN+ACK,并回复 ACK 给客户端(同意释放从服务端到客户端的连接);
- 服务端收到客户端的 ACK 后,释放从服务端到客户端的连接。
TCP 为什么要进行四次挥手?
【问题一】TCP 为什么要进行四次挥手? / 为什么 TCP 建立连接需要三次,而释放连接则需要四次?
【答案一】因为 TCP 是全双工模式,客户端请求关闭连接后,客户端向服务端的连接关闭(一二次挥手),服务端继续传输之前没传完的数据给客户端(数据传输),服务端向客户端的连接关闭(三四次挥手)。所以 TCP 释放连接时服务器的 ACK 和 FIN 是分开发送的(中间隔着数据传输),而 TCP 建立连接时服务器的 ACK 和 SYN 是一起发送的(第二次握手),所以 TCP 建立连接需要三次,而释放连接则需要四次。
【问题二】为什么 TCP 连接时可以 ACK 和 SYN 一起发送,而释放时则 ACK 和 FIN 分开发送呢?(ACK 和 FIN 分开是指第二次和第三次挥手)
【答案二】因为客户端请求释放时,服务器可能还有数据需要传输给客户端,因此服务端要先响应客户端 FIN 请求(服务端发送 ACK),然后数据传输,传输完成后,服务端再提出 FIN 请求(服务端发送 FIN);而连接时则没有中间的数据传输,因此连接时可以 ACK 和 SYN 一起发送。
【问题三】为什么客户端释放最后需要 TIME-WAIT 等待 2MSL 呢?
【答案三】
- 为了保证客户端发送的最后一个 ACK 报文能够到达服务端。若未成功到达,则服务端超时重传 FIN+ACK 报文段,客户端再重传 ACK,并重新计时。
- 防止已失效的连接请求报文段出现在本连接中。TIME-WAIT 持续 2MSL 可使本连接持续的时间内所产生的所有报文段都从网络中消失,这样可使下次连接中不会出现旧的连接报文段。
超时重传
概念:超时重传指的是,发送数据包在一定的时间周期内没有收到相应的ACK,等待一定的时间,超时之后就认为这个数据包丢失,就会重新发送。这个等待时间被称为RTO。
检测丢失segment的方法从概念上讲还是比较简单的,每一次开始发送一个TCP segment的时候,就启动重传定时器,定时器的时间一开始是一个预设的值(Linux 规定为1s),随着通讯的变化以及时间的推移,这个定时器的溢出值是不断的在变化的,如果在ACK收到之前,定时器到期,协议栈就会认为这个片段被丢失,重新传送数据。
TCP在实现重传机制的时候,需要保证能够在同一时刻有效的处理多个没有被确认的ACK,也保证在合适的时候对每一个片段进行重传,有这样几点原则:
- 这些被发送的片段放在一个窗口中,等待被确认,没有确认不会从窗口中移走,定时器在重传时间到期内,每个片段的位置不变。
- 只有等到ACK收到的时候,变成发送并ACK的片段,才会被从窗口中移走。
- 如果定时器到期没有收到对应ACK, 就重传这个TCP segment,重传之后也没有办法完全保证,数据段一定被收到,所以仍然会重置定时器,等待ACK,如果定时器到期还是没有收到ACK,继续重传,这个过程重传的TCP segment一直留着队列之内。
参考:https://blog.csdn.net/wdscq1234/article/details/52476231
https://blog.csdn.net/RENZHADEBENYUAN/article/details/79189707
TCP 拥塞控制
防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提:网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。
发送方维持一个拥塞窗口cwnd的状态变量。发送方让自己的发送窗口小于等于拥塞窗口。
- 慢开始:由小到大的逐渐增大拥塞窗口。首先将cwnd设置为一个最大报文段MMS,在收到一个对新的报文段的确认后,把拥塞窗口增加一个MMS。——指数增长
- 拥塞避免:当慢开始到门限值(ssthresh)后,使用拥塞避免算法(cwnd每次加1)。当发现网络拥塞后,将cwnd置为1,ssthresh减半,再次执行慢开始。
快重传和快恢复
快重传:当接收方收到一个失序报文段后就立即发送重复确认而不要等到自己发送数据时捎带确认。当发送方连续收到三个重复确认时,应立即重传接收方尚未收到的报文段。
快恢复:与快重传结合使用。
- 在连续收到三个重复确认时,将慢开始的ssthresh减半,这是为了防止网络拥塞( ** 接下来并不执行慢开始 ** )。
- 由于发送方现在认为 网络很可能没有拥塞,于是接下来不执行慢开始,而是将cwnd值设置为ssthresh减半后的值,然后执行拥塞避免。
参考:https://blog.csdn.net/jtracydy/article/details/52366461
https://blog.csdn.net/sicofield/article/details/9708383
三、UDP传输层协议
概念
UDP(User Datagram Protocol,用户数据报协议)是 OSI(Open System Interconnection 开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,其传输的单位是用户数据报。
特征
- 面向无连接的传输层协议
- 面向报文
- 首部开销小