计算机网络面试必备知识

UDP 和 TCP 对比

用户数据报协议UDP
(User Datagram Protocol)
传输控制协议TCP
(Transmission Control Protocol)
无连接面向连接
支持一对一、一对多、多对一和多对多交互通信只能是一对一通信
对应用交付的报文直接打包面向字节流
尽最大努力交付,也就是不可靠;
不适用流量控制和拥塞控制
可靠传输;使用流量控制和拥塞控制
首部开销小,仅 8 字节首部最小 20 字节,最大 60 字节

TCP 数据报结构

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议,数据在传输前要建立连接,传输完毕后还要断开连接。

客户端在收发数据前要使用 connect() 函数和服务器建立连接。建立连接的目的是保证IP地址、端口、物理链路等正确无误,为数据的传输开辟通道。

我们来看一下TCP数据报的结构:

带阴影的几个字段需要重点说明一下:

  1. 序列号:Seq(Sequence Number)序列号占32位,用来标识从计算机A发送到计算机B的数据包的序号,计算机发送数据时对此进行标记。
  2. 确认号:Ack(Acknowledge Number)确认号占32位,客户端和服务端都可以发送,Ack = Seq + 1。
  3. 标志位:每个标志位占用1bit,共有6个,分别为 URG、ACK、PSH、RST、SYN、FIN,具体含义如下:
  • 紧急URG:当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
  • 确认ACK:当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
  • 推送PSH:当PUSH=1,表示接收方应该尽快将这个报文交给应用层;
  • 复位RST:当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
  • 同步SYN:在连接建立时用来同步序号;
  • 终止FIN:用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放。

对英文字母缩写的总结:Seq 是 Sequence 的缩写,表示序列;Ack(ACK) 是 Acknowledge 的缩写,表示确认;SYN 是 Synchronous 的缩写,愿意是“同步的”,这里表示建立同步连接;FIN 是 Finish 的缩写,表示完成。

TCP 连接的建立(三次握手)

TCP 的连接建立主要解决一下三个问题:
  1. 使 TCP 双方能够确知对方的存在
  2. 使 TCP 双方能够协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等)
  3. 使 TCP 双方能够对运输实体资源进行分配
TCP “三次握手” 建立连接图解

图片来源https://www.bilibili.com/video/BV1c4411d7jb?p=64

文字描述如下:

刚开始客户端处于 CLOSED 关闭状态,服务端处于 LISTEN 监听状态。然后:

  1. 第一次握手:客户端给服务端发送一个请求报文,这时报文首部中的同步位SYN=1,并设置初始序列号seq=x,此时,客户端进程进入 SYN-SENT 同步已发送状态。
  2. 第二次握手:服务端收到请求报文后,如果同意连接,则发出确认报文。确认报文中 ACK=1,SYN=1,确认号ack=x+1,同时也要为自己初始化一个序列号seq=y,此时,服务端进程进入SYN-RCVD同步已接收状态。
  3. 第三次握手:客户端收到确认后,还要向服务端给出确认。确认报文的 ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入 ESTABLISHED 连接已建立状态。
  4. 当服务端收到客户端的确认后也进入ESTABLISHED 连接已建立状态,此后双方就可以开始通信了。

形象的说明三次握手就像打电话的情况:

1、歪~听得到吗?

2、听得到,你呢?

3、我也听得到。

然后才开始真正对话

以上这些可能还不足以应付三次握手,面试官可能还会问些其他细节问题,比如:

- 为什么TCP客户端最后还要发送一次确认?

如果使用的是两次握手建立连接,假设有下图这样一种场景

客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

简而言之,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。

- seq初始序列号是固定的吗

三次握手的一个重要功能是客户端和服务端交换初始序列号,以便让对方知道接下来接受数据的时候如何按序列号组装数据。

如果初始序列号是固定的,攻击者很容易猜出后续的确认号,所以初始序列号是动态生成的。

- 什么是半连接队列

服务端第一次收到客户端的 SYN 后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立连接,服务器会把这种状态下请求连接放在一个队列里,我们吧这种队列称为半连接队列。当然还有全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。

- 三次握手过程中可以携带数据吗

TCP规定:SYN报文段(SYN=1)不能携带数据,但需要消耗一个序列号。ACK报文段可以携带数据,但是如果不携带数据则不消耗序列号。

也就是说第一次、第二次握手不可以携带数据,而第三次握手时可以携带数据的。

为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。也就是说,第一次握手可以放数据的话,其中一个简单的原因就是会让服务器更加容易受到攻击。

而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态,也就是说,对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以携带数据是没问题的。

TCP 连接的释放(四次挥手)

TCP “四次挥手” 释放连接图解

文字描述如下:

刚开始双方都处于 ESTABLISHED 连接已建立状态,假如是客户端发起的关闭请求,则:

  1. 第一次挥手:客户端发出连接释放报文,并且停止发送数据。释放报文首部中终止位 FIN =1,序列号 seq=u (等于前面已经传送过来的数据的最后一个字节的序号加1)。此时,客户端进入 FIN-WAIT-1 终止等待1 状态。
  2. 第二次挥手:服务端收到释放报文后,发出 ACK 确认报文,并把客户端的序列号+1作为ack确认号,并且带上自己的序列号seq=v。此时,服务端进入 CLOSE-WAIT 关闭等待状态。
  3. 客户端收到服务端的确认请求后,此时,客户端进入 FIN-WAIT-2 终止等待2 状态,等待服务端发送连接释放报文。
  4. 第三次挥手:服务端将最后的数据发送完毕后,就像客户端发送连接释放报文,FIN=1,序列号seq=w。此时,服务端进入 LAST-ACK 最后确认状态,等待客户端的确认。
  5. 第四次挥手:客户端收到释放报文后,发出 ACK 确认报文,并把服务端的序列号+1作为ack确认号,并且带上自己的序列号seq=u+1。此时,客户端进入 TIME-WAIT 时间等待状态。注意此时TCP连接还没有释放,必须等待 2倍的MSL(最长报文段寿命)的时间后,以确保服务端收到自己的 ACK 报文之后才进入 CLOSED 关闭状态。
  6. 服务端收到 ACK 确认报文后,就进入 CLOSED 关闭状态。

可以形象的理解为下课情况:

1、老师,下课了

2、好,我知道了,我说完这点

3、好了,说完了,下课吧

4、谢谢老师,老师再见

“四次挥手”也有几个地方需要特别注意,比如:

- 为什么客户端最后还要等待 2MSL?

MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。

第一,如下图这种情况,因为客户端最后的ACK报文有可能丢失,就会造成服务端进行超时重传,如果客户端直接进入关闭状态,则会导致服务端反复重传无法进入关闭状态。而客户端进入时间等待状态至少是一个报文的来回时间,就可以确保服务端可以收到最后一个ACK确认报文而进入关闭状态。

第二,防止类似于“三次握手”中提到的“已经失效的连接请求报文“出现在本连接中。客户端发送最后一个确认报文后,在这个 2MSL 时间中,就可以使本连接持续的时间内所有产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

- 为什么建立连接是三次握手,关闭连接却是四次挥手呢?

建立连接的时候,服务端在 LISTEN 状态,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。

而关闭连接是,服务端收到客户端的FIN报文时,仅仅表示客户端不再发送数据了但是还能接收数据,并且自己也未必将全部数据都发送给对方了,所以自己可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,自己的ACK和FIN一般会分开发送,从而导致多了一次。

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

TCP 设有一个保活计时器,客户端如果出现故障,服务端当然不能一直等下去,白白浪费资源。服务端每收到一次客户端的请求都会重新复位这个计时器,时间通常设置为2小时,若2小时还没有收到客户端的任何数据,服务端就会发送一个探测报文,以后每隔75秒发送一次,若一连发送10个探测报文仍没反应,服务端就认为客户端出了故障,接着就关闭连接。

ref:

计算机网络微课堂

【超详细分析】关于三次握手与四次挥手面试官想考我们什么?

两张动图-彻底明白TCP的三次握手与四次挥手

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值