文章

TCPUDP

TCPUDP

TCP/IP

网络分层(TCP/IP 四层模型 vs OSI 七层模型)

3e74a

什么是 TCP/IP?

TCP/IP 一般指的是 TCP/IP 协议簇
TCP:Transmission Control Protocol 翻译过来就是传输控制协议,TCP 协议是一个面向连接的、可靠的、基于字节流的传输层协议

TCP、UDP 传输有什么区别?如何优化 UDP 传输?UDP 传输的数据包与 TCP 传输的数据包有什么区别?

1、TCP 和 UDP 概念和特点

TCP 的优点: 可靠,稳定 TCP 的可靠体现在 TCP 在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。
TCP 的缺点: 慢,效率低,占用系统资源高,易被攻击 TCP 在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的 CPU、内存等硬件资源。 而且,因为 TCP 有确认机制、三次握手机制,这些也导致 TCP 容易被人利用,实现 DOS、DDOS、CC 等攻击。
UDP 的优点: 快,比 TCP 稍安全,UDP 没有 TCP 的握手、确认、窗口、重传、拥塞控制等机制,UDP 是一个无状态的传输协议,所以它在传递数据时非常快。没有 TCP 的这些机制,UDP 较 TCP 被攻击者利用的漏洞就要少一些。但 UDP 也是无法避免攻击的,比如:UDP Flood 攻击……
UDP 的缺点: 不可靠,不稳定 因为 UDP 没有 TCP 那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。

2、TCP 和 UDP 区别?

zksco

  • TCP 是面向连接的,TCP 传输数据之前需要三次握手;UDP 是面向无连接的,即发送数据之前不需要建立连接
  • TCP 提供可靠的服务(TCP 连接传输的数据,无差错,不丢失,不重复,按序列到达);UDP 尽最大努力交付,即不保证可靠交付
  • TCP 面向字节流,实际上 TCP 把数据看成一连串无结构的字节流;UDP 是面向报文的
  • UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速度降低(对实时应用很有用,如 IP 电话、实时视频会议等)
  • 每一条 TCP 连接只能是点到点的;UDP 支持一对一,一对多,多对一和多对多的交互通信
  • TCP 首部开销 20 字节;UDP 的首部开销小,只有 8 字节
  • TCP 的逻辑通信信道是全双工的可靠信道;UDP 则是不可靠信道

3、UDP 存在的问题?怎么优化?

一是数据包容易丢失,二是数据包**无序 **

4、TCP 和 UDP 报文结构

1
2
3
4
5
6
7
8
9
10
11
源端口 16
目标端口 16
序列号 32
回应序号 32
TCP头长度 4
reserved 6
控制代码 6
窗口大小 16
偏移量 16
校验和 16
选项  32(可选)
1
2
3
4
源端口 16
目的端口 16
长度 16
校验和 16

TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?

这两个完全是两样不同东西,实现的层面也不同:

  • HTTP 的 keep-alive,是由应用层(用户态) 实现的,称为 HTTP 长连接;一个 TCP 连接多次使用
  • TCP 的 keep-alive,是由 TCP 层(内核态) 实现的,称为 TCP 保活机制;TCP 的 keep-alive 仅仅是为了维持连接的正常,保证连接不被断开,因此 TCP 会间隔的发送数据包检测是否连接正常,这个间隔的时间就是 “keep-alive” 的作用。

阿里一面:TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗? https://zhuanlan.zhihu.com/p/479813348

TCP 拥塞?TCP 拥塞控制原理?

TCP 拥塞的背景:TCP/IP 协议栈开始广泛运行是,网络开始遭受拥塞崩溃:即数据发送主机会以建议允许的速度将其数据包发送到互联网,当某些路由器发生拥塞,导致数据包被丢弃;对于 TCP 这种有重传机制的传输协议,当发生数据丢失时,重传数据将延长数据到达的时间;同时,高频率的重传,也将导致网络的拥塞得不到缓解,从而引发更多的拥塞
TCP 拥塞控制:让每个源确定网络中有多少可用容量,以便它知道可以安全传输多少数据包,防止过多的数据注入到网络中,使网络中的路由或链路不至于过载。在网络中发生拥塞时,拥塞控制减少向网络中发送数据的速度,防止造成恶性循环;同时在网络空闲时,提高发送数据的速度,最大限度地利用网络资源。拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素
几种拥塞控制方法:慢开始 ( slow-start )、拥塞避免 ( congestion avoidance )、快重传 ( fast retransmit ) 和快恢复 ( fast recovery )。

报文结构与 http 有什么不同?

TCP 粘包

TCP 是怎么保证可靠传输的?

什么是可靠传输?
可靠传输就是保证接收方收到的字节流和发送方发出的字节流是完全一样的
TCP 如何保证可靠性的?
网络层是没有可靠传输机制的,尽自己最大的努力进行交付。而传输层使用 TCP 实现可靠传输,TCP 保证可靠传输的机制有如下几种:

  1. 校验和 Checksum(稍作了解即可)

TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。

  1. 序列号和确认应答机制(重要)

TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。

  1. 重传机制(重要)

当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

  1. 流量控制(滑动窗口协议)(非常重要)

流量控制指的是让发送方发送速率不要太快;TCP 连接的每一方都有固定大小的缓冲空间,TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)

  1. 拥塞控制(重要)

当网络拥塞时,减少数据的发送。不同于流量控制考虑的是点对点的通信量控制,拥塞控制考虑的是整个网络,是一个全局性的考虑。 拥塞控制算法:

  • 慢启动
  • 拥塞避免算法
  1. 数据合理分片与排序

TCP 会对数据进行分片,接收方会缓存为按序到达的数据,重新排序后再提交给应用层。

TCP 三次握手和四次挥手

关于 TCP 三次握手和四次挥手,满分回答在此

重要标志位

  1. ACK:Acknowledge Character,确认字符 TCP 协议规定,只有 ACK=1 时有效,也规定连接建立后所有发送的报文的 ACK 必须为 1
  2. SYN:Synchronize Sequence Numbers,同步序列编号,在建立连接时用来同步序号。当 SYN=1 而 ACK=0 时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使 SYN=1 和 ACK=1,因此 SYN 置 1 就表示这是一个连接请求或连接接受报文
  3. FIN: Finish 终结,用来释放一个连接。当 FIN=1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。

SEQ:Sequence Number,序列号

三次握手

TCP 三次握手,其实就是建立一个 TCP 连接,客户端与服务器交互需要 3 个数据包,1.5RTT。握手的主要作用就是为了确认双方的接收和发送能力是否正常,初始序列号,交换窗口大小以及 MSS 等信息。
l3rv2

  1. 第一次握手:建立连接。客户端发送连接请求报文段,将 SYN 位置为 1 且 seq 为 x;然后客户端进入 SYN_SEND 状态,等待服务器确认;即 A 发送信息给 B。
  2. 第二次握手:服务器 B 收到 SYN 报文段。服务器收到客户端的 SYN 报文段,需要对这个 SYN 报文段进行确认,(ACK=x+1),同时自己也发送一个 SYN=1 报文(seq=y),即 SYN+ACK 报文,此时服务器 B 进入 SYN_RECV 状态。
  3. 第三次握手:客户端 A 收到服务器 B 的 SYN+ACK 报文段。客户端 A 向服务器 B 发送报文段 ACK(ACK=y+1),此报文段发送完毕,客户端 A 和服务器 B 进入 ESTABLISHED 状态,完成三次握手。客户端与服务器开始传送数据。

TCP 三次握手,其实就是 TCP 应用在发送数据前,通过 TCP 协议跟通信对方协商好连接信息,建立起 TCP 的连接关系。

四次挥手

zbkvk

  1. 客户端发送 FIN 释放连接请求报文,用来关闭客户端到服务器的数据传送(Client 发送释放信息给 Server,发出去之后,Client→Server 发送数据这条路径就断了)
  2. 服务器收到这个 FIN 并确认,它发回一个 ACK,确认序号为收到的序号加 1 。和 SYN 一样,一个 FIN 将占用一个序号(Server 收到 Client 的释放信息之后,回复确认释放的信息,Server 同意 Client 的释放连接请求)
  3. 服务器发送关闭与客户端的连接请求报文,发送一个 FIN 给客户端(Server 发送请求释放连接信息给 Client)
  4. 客户端发送 ACK 报文确认,并将确认序号设置为收到序号加 1(Client 收到 Server 发送的信息后向 Server 发送确认释放信息,Client 同意 Server 的释放连接请求,Server 收到确认信息后就会正式关闭连接;Client 等待 2MSL 后依然没有收到回复,则证明 Server 已正常关闭,于是 Client 关闭连接)

TCP 为什么是 3 次握手?不是 2 次,不是 4 次?

我们可以从几个方面来解释:

1、确认双方的收发能力

TCP 建立连接之前,需要确认客户端与服务器双方的收包和发包的能力。
1. 第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。

  1. 第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
  2. 第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。

所以,只有三次握手才能确认双方的接收与发送能力是否正常

2、序列号可靠同步

如果是两次握手,服务端无法确定客户端是否已经接收到了自己发送的初始序列号,如果第二次握手报文丢失,那么客户端就无法知道服务端的初始序列号,那 TCP 的可靠性就无从谈起。

3、阻止重复历史连接的初始化

客户端由于某种原因发送了两个不同序号的 SYN 包,我们知道网络环境是复杂的,旧的数据包有可能先到达服务器。如果是两次握手,服务器收到旧的 SYN 就会立刻建立连接,那么会造成网络异常。
如果是三次握手,服务器需要回复 SYN+ACK 包,客户端会对比应答的序号,如果发现是旧的报文,就会给服务器发 RST 报文,直到正常的 SYN 到达服务器后才正常建立连接。
所以三次握手才有足够的上下文信息来判断当前连接是否是历史连接。

4、安全问题

我们知道 TCP 新建连接时,内核会为连接分配一系列的内存资源,如果采用两次握手,就建立连接,那会放大 DDOS 攻击的。
TCP 作为一种可靠传输控制协议,其核心思想:既要保证数据可靠传输,又要提高传输的效率,而三次握手恰好可以满足以上两方面的需求!

TCP 为什么需要握手这个操作?

原因: TCP 是可靠通信协议, 全双工,为保证传输的可靠性,需要给每次传输的数据段添加序号,那么初始的序列号就是 TCP 三次握手真正的意义所在,而为了确保交换双方的初始序号,最少需要三次才行。
前两次握手
为了保证服务端能接收到客户端的信息并能做出正确的应答而进行前两次握手。
后两次握手
为了保证客户端能接收到服务端的信息并能做出正确的应答而进行的后两次握手。

TCP 挥手的目的

为了保证双方都能通知对方需要释放连接,即在释放连接后都无法接收或发消息给对方。

TCP 第四次握手时,为什么要等待 2 MILS?

  1. 确保客户端发送的第四次 ack 报文服务器能收到(因为最后一次挥手报文没有确认,我们需要确保 Client 的 ACK 可以到达 Server,如果 2MSL 时间内没有收到,则 Server 会重发)
  2. 2MSL 时间可以保证当 Server 没有收到确认时,Server 可以再次发送 FIN 报文,并且 Client 可以再次收到并重新发送确认,所以 2MSL 的时间可以保证连接正常结束
  3. 确保当前连接的所有报文都已经过期,防止旧数据滞留网络,影响新的连接

Socket

什么是 Socket?

Socket(套接字) 是通信的基石,是支持 TCP/IP 协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的信息:连接使用的协议,本地主机的 IP 地址,本地进程的协议端口,远端主机的 IP 地址,远端进程的协议端口。

Socket 断线重连实现

正常连接断开客户端会给服务器发送一个 FIN 报文,服务器收到 FIN 后才会知道连接断开。而断网断电等异常情况客户端无法发送 FIN 给服务器,所以服务器没法检测到客户端已经断线。
为了缓解这个问题,服务器需要有个心跳机制,就是服务端检测到某个客户端多久没发送任何数据过来就认为客户端已经断开,这需要客户端定时向服务器发送心跳数据来维持连接不断开。

心跳机制

什么是长连接?
长连接是建立连接之后,不主动断开,双方互相发送数据,发完了也不主动断开连接,之后有需要发送的数据就继续通过这个连接发送。
为什么需要心跳?
主要是为了防止 NAT 超时,客户端隔一段时间就主动发一个数据,探测连接是否断开。

移动网络并不在 Internet 中,而是在运营商的内网,并不具备真正的公网 IP,因此当某个 TCP 连接在一段时间不通信之后,网关会出于网络性能的考虑而关闭这条 TCP 连接和公网的连接通道,导致这个 TCP 端口不再收到外部通信消息,即 TCP 连接被动关闭。

在一定间隔时间内,使用 TCP 连接发送超短无意义的消息来让网关不能将自己定义为空闲连接,从而防止网关将自己的连接关闭。
服务器如何处理心跳包?
假如客户端心跳间隔是固定的,那么服务器在连接闲置超过这个时间还没收到心跳时,可以认为对方掉线,就可以关闭连接;如果客户端心跳会动态变动,应当设置一个最大值,超过这个最大值才认为对方掉线;还有一种情况就是服务器通过 TCP 连接主动给客户端发消息出现写超时,可以直接认为对方掉线。

WebSocket

HTTP 与 WebSocket 区别与联系

  1. Http 与 WebSocket 是两个完全不同的协议,都是基于 TCP 的。两者唯一的联系是 WebSocket 利用 HTTP 进行握手;具体说明请看 RFC6455-1.7。
  2. WS 默认也使用 80 端口;WSS 默认也使用 443 端口。当然如果这个也算是和 HTTP 的联系的话,那么你说的也对。
  3. HTTP 协议局限性一大堆,比如明文传输、无法保证信息完整性、没有身份验证等。而 WebSocket 的出现则是为了解决 HTTP 协议只能由 Client 发起通信请求的问题。WebSocket 是全双工通信。

IP 报文

IP 报文作用

  1. IP 协议使得复杂的实际网络变为一个虚拟互连的网络
  2. IP 协议使得网络层可以屏蔽底层细节而专注网络层的数据转发
  3. IP 协议解决了虚拟网络中数据包传输路径的问题

面试题

TCP 和 Socket 关系?

HTTPS 中 TLS 和 TCP 能同时握手吗?

不能,先 TCP 的 3 次握手建立 TCP 连接,再是 TLS 握手

如何设计在 UDP 上层保证 UDP 的可靠性传输?

传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现方式可以参照 TCP 可靠性传输的方式:

  1. 添加 seq/ack 机制,确保数据发送到对端
  2. 添加发送和接收缓冲区,主要是用于添加超时重传机制

Ref

本文由作者按照 CC BY 4.0 进行授权