计算机网络_03_传输层(个人总结)

    声明: 1. 本文为我的个人复习总结, 并那种从零基础开始普及知识 内容详细全面, 言辞官方的文章
              2. 由于是个人总结, 所以用最精简的话语来写文章
              3. 若有错误不当之处, 请指出

基础

TCP 头部格式:

计算机网络_03_传输层(个人总结)_第1张图片

TCP是什么?

TCP 是面向连接的、可靠的、基于字节流的传输层通信协议

面向连接:

⼀定是⼀对⼀才能连接, 不能像 UDP 协议可以⼀个主机同时向多个主机发送消息

可靠:

序列号可以保证数据 不重不漏有序;

ack确认应答, ack=1000代表前999的数据全都接收到了

重传机制、滑动窗口、流量控制、拥塞控制 等机制

字节流:

消息是「没有边界」的

连接:

Socket + 序列号 + 窗口大小

用于保证可靠性流量控制维护的某些状态信息

如何唯一确定一个 TCP 连接?

四元组(源地址 + 源端口 + 目的地址 +目的端口)

TCP 的最大连接数是多少?

理论Max=客户端ip数(2^32) * 客户端端口数(2^16)

实际上要受到两个限制:

  1. 内存限制

    每个 TCP 连接都要占用一定内存

  2. 文件描述符限制(新建 或 打开 的文件)

    每个Socket都是一个文件

UDP 头部格式:

计算机网络_03_传输层(个人总结)_第2张图片

TCP 和 UDP 区别:

  1. 连接

    TCP 是⾯向连接的传输层协议,传输数据前先要建⽴连接。

    UDP 是不需要连接,即刻传输数据。

  2. 服务对象

    TCP 是⼀对⼀的两点服务,即⼀条连接只有两个端点。

    UDP ⽀持⼀对⼀、⼀对多、多对多的交互通信

  3. 可靠性

    TCP 是可靠交付数据的,数据可以⽆差错、不丢失、不᯿复、按需到达。

    UDP 是尽最⼤努⼒交付,不保证可靠交付数据。

  4. ⾸部开销

    TCP ⾸部⻓度较⻓,会有⼀定的开销,⾸部在没有使⽤「选项」字段时是 20 个字节,如果使⽤了「选项」

    字段则会变⻓的。

    UDP ⾸部只有 8 个字节,并且是固定不变的,开销较⼩。

  5. 传输⽅式

    TCP 是流式传输,没有边界,但保证顺序和可靠。

    UDP 是⼀个包⼀个包的发送,是有边界的,但可能会丢包和乱序。

  6. 分⽚不同

    TCP 的数据⼤⼩如果⼤于 MSS ⼤⼩,则会在传输层进⾏分⽚,⽬标主机收到后,也同样在传输层组装 TCP

    数据包,如果中途丢失了⼀个分⽚,只需要传输丢失的这个分⽚。

    UDP 的数据⼤⼩如果⼤于 MTU ⼤⼩,则会在 IP 层进⾏分⽚,⽬标主机收到后,在 IP 层组装完数据,接着

    再传给传输层,但是如果中途丢了⼀个分⽚,在实现可靠传输的 UDP 时则就需要᯿传所有的数据包,这样

    传输效率⾮常差,所以通常 UDP 的报⽂应该⼩于 MTU。

  7. 拥塞控制、流量控制

    TCP 有拥塞控制和流ᰁ控制机制,保证数据传输的安全性。UDP 则没有,即使⽹络⾮常拥堵了,也不会影响 UDP 的发送速率。

TCP 和 UDP 应⽤场景:

TCP:

  1. FTP ⽂件传输

  2. HTTP / HTTPS

UDP:

  1. 电话, 直播
  2. 垃圾短信

粘包:

TCP会粘包: 若连续几次需要send的数据都很少,通常TCP会根据Nagle优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据.
UDP不会粘包: 每个UDP段都是一条消息 不能一次提取任意字节的数据 不会使用块的合并优化算法, 每个UDP包中就有了消息头(消息来源地址,端口等信息), 有消息保护边界, 提取相应包的数据

Nagle 算法

该算法的思路是延时批处理, 要满足以下两个条件才进行发送

  1. 要等到窗⼝⼤⼩ >= MSS 或是 数据大小 >= MSS
  2. 收到之前发送数据的 ack 回包

为什么 UDP 头部没有「⾸部⻓度」字段,⽽ TCP 头部有「⾸部⻓度」字段呢?

TCP 有可变⻓的「选项」字段,⽽ UDP 头部⻓度则是不会变化的,⽆需多⼀个字段去记录 UDP 的⾸部⻓

度。

为什么 UDP 头部有「包⻓度」字段,⽽ TCP 头部则没有「包⻓度」字段呢?

在这里插入图片描述

UDP 「包⻓度」是冗余的, 是padding的

半连接队列:

SYN队列, 完成了2次握手

全连接队列:

Accept队列, 完成了3次握手

TCP 三次握手:

计算机网络_03_传输层(个人总结)_第3张图片

  1. 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送的字段中包含标志位SYN=1,序列号seq=x。第一次握手前客户端的状态为CLOSE,第一次握手后客户端的状态为SYN-SENT。此时服务端的状态为LISTEN
  2. 第二次握手:服务端在收到客户端发来的报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复一段报文,其中包括标志位SYN=1ACK=1,序列号seq=y,确认号ack=x+1。第二次握手前服务端的状态为LISTEN,第二次握手后服务端的状态为SYN-RCVD,此时客户端的状态为SYN-SENT。(其中SYN=1表示要和客户端建立一个连接,ACK=1表示确认序号有效)
  3. 第三次握手:客户端收到服务端发来的报文后,会再向服务端发送报文,其中包含标志位ACK=1,序列号seq=x+1,确认号ack=y+1。第三次握手前客户端的状态为SYN-SENT,第三次握手后客户端和服务端的状态都为ESTABLISHED此时连接建立完成。

TCP为什么要建立连接/为什么要三次握手, 不能两次?

为了数据的可靠传输

  1. 防止历史连接的建立, 减少不必要的资源开销

  2. 让双方同步初始化序列号

    序列号能保证数据包进行 不重复、不缺少、按序 的传输

TCP为什么要三次握手, 不能四次?

三次握手即可建立安全可靠的连接, 无需第四次握手

为什么每次的初始序列号 ISN 是不相同的?

  1. 防止已失效连接被使用
  2. 防止黑客伪造 ISN

既然 IP 层会分片,为什么 TCP 层还需要 MSS 呢?

MTU :⼀个⽹络包的最⼤⻓度

MSS :除去 IP 和 TCP 头部之后,⼀个⽹络包所能容纳的 TCP 数据的最⼤⻓度;

粒度更细, 进⾏重发时也是以 MSS 为单位,⽽不⽤᯿传所有的分⽚,⼤⼤增加了重传的效率。

SYN 攻击:

攻击者短时间伪造不同 IP 地址的 SYN 报⽂,服务端每接收到

⼀个 SYN 报⽂,就进⼊ SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报⽂,⽆法得到未知 IP 主机的

ACK 应答,久⽽久之就会占满服务端的 SYN 接收队列(未连接队列),使得服务器不能为正常⽤户服务

解决方案:

修改 Linux 内核参数,控制队列⼤⼩和当队列满时应做什么处理

TCP 四次挥手:

计算机网络_03_传输层(个人总结)_第4张图片

  1. A的应用进程先向其TCP发出连接释放报文段(FIN=1,seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1(终止等待1)状态,等待B的确认。
  2. B收到连接释放报文段后即发出确认报文段(ACK=1,ack=u+1,seq=v),B进入CLOSE-WAIT(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。
  3. A收到B的确认后,进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。
  4. B发送完数据,就会发出连接释放报文段(FIN=1,ACK=1,seq=w,ack=u+1),B进入LAST-ACK(最后确认)状态,等待A的确认。
  5. A收到B的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),A进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL(最大报文段生存时间)后,A才进入CLOSED状态。B收到A发出的确认报文段后关闭连接,若没收到A发出的确认报文段,B就会重传连接释放报文段。

最后一次的ACK, 是为了确保客户端收到了FIN

主动关闭连接的(客户端),才有 TIME_WAIT 状态

为什么挥⼿需要四次?

ACK 和 FIN ⼀般都会分开发送,从⽽⽐三次握⼿导致多了⼀次

  1. 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。

  2. 服务器收到客户端的 FIN 报⽂时,先回⼀个 ACK 应答报⽂,⽽服务端可能还有数据需要处理和发送,等

  3. 服务端不再发送数据时,才发送 FIN 报⽂给客户端来表示同意现在关闭连接

为什么 TIME_WAIT 等待的时间是 2MSL?

MSL 是报⽂最⼤⽣存时间

如果在 TIME-WAIT 时间内,因为客户端的 ACK没有传输到服务端,客户端⼜接收到了服务端᯿发的 FIN 报⽂,那么 2MSL 时间将重新计时

  1. 保证客户端发送的最后一个ACK报文段能够到达服务端
  2. 使这个连接产生的所有报文段都从网络中消失,使下一个新的连接中不会出现旧的连接请求报文段

TIME_WAIT和CLOSE_WAIT的区别在哪?

CLOSE_WAIT是被动关闭形成的,当客户端发送FIN报文,服务端返回ACK报文后进入CLOSE_WAIT。

TIME_WAIT是主动关闭形成的,当第四次挥手完成后,客户端进入TIME_WAIT状态。

如果已经建⽴了连接,但是客户端突然出现故障了怎么办?

TCP 有保活机制, 每隔⼀个时间间隔 发送⼀个探测报⽂

Socket编程:

监听的 socket 和真正⽤来传送数据的 socket,是「两个」 socket

计算机网络_03_传输层(个人总结)_第5张图片

TCP可靠传输

重传机制:

超时重传:

久久收不到ACK应答, 以时间作为驱动

超时重传时间 RTO 的值 是⼀个动态变化的值:

每当遇到⼀次超时重传的时候,说明网络可能比较拥堵, 都会将下⼀次超时时间间隔设为先前值的两倍

可能原因:

  1. 数据包丢失
  2. ack丢失

快速重传:

以数据驱动, 当收到三个相同的 ACK 报⽂时, 便会进行重传, 但不清楚丢的是哪个, 所以此批次的全部重传

计算机网络_03_传输层(个人总结)_第6张图片

SACK:

通过SACK字段可以清楚具体是哪个数据包丢失了

DSACK:

告诉「发送⽅」有哪些数据被重复接收了(即数据包没丢, 而是ack丢了; 网络延时收到旧的数据包)

滑动窗口:

窗⼝⼤⼩就是指⽆需等待确认应答,⽽可以继续发送数据的最⼤值

通常窗⼝的⼤⼩是由接收⽅的窗⼝⼤⼩来决定的

发送方窗口:

计算机网络_03_传输层(个人总结)_第7张图片

接收方窗口:

计算机网络_03_传输层(个人总结)_第8张图片

流量控制:

背压机制, 让「发送⽅」根据「接收⽅」的实际接收能⼒控制发送的数据量

发送窗⼝和接收窗⼝中所存放的字节数,都是放在操作系统内存缓冲区中的,⽽操作系统的缓冲区,会被操作系统调整

如果发⽣了先减少缓存,再收缩窗⼝,就会出现丢包的现象

为了防⽌这种情况发⽣,TCP 规定是不允许同时减少缓存⼜收缩窗⼝的,⽽是采⽤先收缩窗⼝ 过段时间再减少缓存

窗⼝关闭:

即停止发送数据

之后会有窗⼝探测报⽂, 探测是否可以开启窗口

拥塞控制:

  1. 慢启动

  2. 拥塞避免

  3. 拥塞发⽣

    • 超时重传
    • 快速重传
  4. 快速恢复

    快速重传时才有

超时重传时(不好):

计算机网络_03_传输层(个人总结)_第9张图片

快速重传时:

计算机网络_03_传输层(个人总结)_第10张图片

你可能感兴趣的:(计算机网络)