TCP协议

1. TCP 和 UDP 的区别?

首先概括一下基本的区别:

TCP是一个面向连接的、可靠的、基于字节流的传输层协议。UDP是一个面向无连接、面向数据报的传输层协议。

TCP通信类似于要打个电话,接通并确认身份后,才开始进行通行;
UDP通信类似于学校广播,靠着广播播报直接进行通信。

具体来分析,TCP 有三大核心特性:

  1. 面向连接。在客户端和服务器通信之前,TCP 需要三次握手建立连接;而 UDP 没有相应建立连接的过程,数据传输前后不连接,发送端只负责将数据发送到网络,接收端从消息队列读取。

  1. 可靠性。传输过程采用一些等手段确保数据无差错,不丢失。UDP 则尽可能传递数据,但不保证传递交付给对方。

TCP 会精准记录哪些数据发送了,哪些数据被对方接收了,哪些没有被接收到,而且保证数据包按序到达,不允许半点差错。这是 有状态
当意识到丢包了或者网络环境不佳,TCP 会根据具体情况调整自己的行为,控制自己的发送速度或者重发。这是 可控制
  1. 面向字节流,TCP 为了维护状态,将应用层报文看成一串无结构的字节流,拆分为多个TCP报文段传输,也有可能将多条消息组成一个 TCP 报文进行传输。UDP 面向数据报文,不拆分不合并,只是在其上面加上首部后就交给了下面的网络层。

这是因为在发送端,当我们调用 send 函数完成数据 发送 以后,数据并没有真正从网络上发送出去,而是从应用程序拷贝到了操作系统内核协议栈中,至于什么时候真正被发送, 取决于发送窗口、拥塞窗口以及当前发送缓冲区的大小等条件。也就是说,我们不能认为每次 send 调用发送的数据,都会作为一个整体完整的消息被发送出去。
  1. TCP 只能点对点全双工通信。UDP 支持一对一、一对多、多对一和多对多的交互通信

对某些实时性要求比较高的情况使用UDP,比如游戏,媒体通信,实时直播,即使出现传输错误也可以容忍;其它大部分情况下,HTTP都是用TCP,因为要求传输的内容可靠,不出现丢失的情况

2. 说说 TCP 三次握手的过程?为什么是三次而不是两次、四次?

以谈恋爱为例,两个人能够在一起最重要的事情是首先确认各自被爱的能力。接下来我们以此来模拟三次握手的过程。

第一次:

男: 我爱你。

女方收到。

由此证明男方拥有爱的能力。

第二次:

女: 我收到了你的爱,我也爱你。

男方收到。

OK,现在的情况说明,女方拥有爱和被爱的能力。

第三次:

男: 我收到了你的爱。

女方收到。

现在能够保证男方具备被爱的能力。

由此完整地确认了双方爱和被爱的能力,两人开始一段甜蜜的爱情。

对应到 TCP 的三次握手,也是需要确认双方的两样能力: 发送的能力和接收的能力。于是便会有下面的三次握手的过程:

  1. 第一次握手:Client将SYN置1,随机产生一个初始序列号seq发送给Server,进入SYN_SENT状态;

  1. 第二次握手:Server收到Client的SYN=1之后,知道客户端请求建立连接,将自己的SYN置1,ACK置1,产生一个acknowledge number=sequence number+1,并随机产生一个自己的初始序列号,发送给客户端;进入SYN_RCVD状态;

  1. 第三次握手:客户端检查acknowledge number是否为序列号+1,ACK是否为1,检查正确之后将自己的ACK置为1,产生一个acknowledge number=服务器发的序列号+1,发送给服务器;进入ESTABLISHED状态;服务器检查ACK为1和acknowledge number为序列号+1之后,也进入ESTABLISHED状态;完成三次握手,连接建立。

  • 简单来说就是 :

  1. 客户端向服务端发送SYN

  1. 服务端返回SYN,ACK

  1. 客户端发送ACK

第一次握手

客户端会随机初始化序号(client_isn),将此序号置于 TCP 首部的「序列号」字段中,同时把 SYN 标志位置为 1 ,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态。

第一个报文—— SYN 报文如下图所示:

第二次握手

服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序列号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYN 和 ACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。

第二个报文 —— SYN + ACK 报文如下图所示:

第三次握手

客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。

第三个报文 —— ACK 报文如下图所示:

握手之后:服务器收到客户端的应答报文后,也进入 ESTABLISHED 状态;

从上面的过程可以发现第三次握手是可以携带数据的(前两次握手是不可以携带数据),服务器必须等收到 ACK 分组之后才能发送数据,这也是面试常问的题。

一旦完成三次握手,双方都处于 ESTABLISHED 状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。

两次握手行不行?服务端无法确认客户端的接受能力,那服务端可以认为客户端没有收到,就会重传,造成服务端资源浪费
第一次挥手

客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。

第二次挥手

服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。

客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。

第三次挥手

等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。

第四次挥手

客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态。

服务器收到了 ACK 应答报文后,就进入了 CLOSED 状态,至此服务端已经完成连接的关闭。

客户端在经过 2MSL 一段时间后,自动进入 CLOSED 状态,至此客户端也完成连接的关闭。

每个方向都需要一个 FIN 和一个 ACK,因此通常被称为 四次挥手,不过需要注意的是,主动关闭连接的,才有 TIME_WAIT 状态

3. TCP报文

  • 序列号(Sequence Number):在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。

  • 确认应答号(Acknowledgement Number):指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决丢包的问题。

  • 控制位:

  • ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。

  • RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。

  • SYN:该位为 1 时,表示希望建立连接,并在其「序列号」的字段进行序列号初始值的设定。

  • FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位为 1 的 TCP 段。

  • URG:紧急标志位,表示的是此报文段中有紧急数据,将紧急数据排在普通数据的前面;当接受端收到此报文后后必须先处理紧急数据,而后再处理普通数据。

  • PSH:催促标志位,当发送端将 PSH 置为1时,TCP会立即创建一个报文并发送。接受端收到 PSH 为1的报文后就立即将接受缓冲区内数据向上交付给应用程序,而不是等待缓冲区满后再交付。

  • 窗口大小:用于 TCP 流量控制。告诉对方本端的 TCP 接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。

  • 校验和:由发送端填充,接收端对 TCP 报文段执行 CRC 算法以检验 TCP 报文段在传输过程中是否损坏,检验的范围包括头部、数据两部分,是 TCP 可靠传输的一个重要保障。

  • 紧急指针:一个正的偏移量。它和序列号字段的值相加表示最后一个紧急数据的下一个字节的序列号,用于发送端向接收端发送紧急数据。

【网络协议】万文长篇,带你深入理解 TCP;场景复现,掌握鲜为人知的细节(中)

【网络协议】万文长篇,带你深入理解 TCP;场景复现,掌握鲜为人知的细节(下)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值