传输层面试题

三次握手和四次挥手机制

三次握手
在这里插入图片描述
三次握手是 TCP 连接的建立过程。在握手之前,主动打开连接的客户端结束 CLOSE 阶段,被动打开的服务器也结束 CLOSE 阶段,并进入 LISTEN 阶段。随后进入三次握手阶段:

① 首先客户端向服务器发送一个 SYN 包,并等待服务器确认,其中:
标志位为 SYN,表示请求建立连接;
序号为 Seq = x(x 一般为 1);
随后客户端进入 SYN-SENT 阶段。

② 服务器接收到客户端发来的 SYN 包后,对该包进行确认后结束 LISTEN 阶段,并返回一段 TCP 报文,其中:
标志位为 SYN 和 ACK,表示确认客户端的报文 Seq 序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接;
序号为 Seq = y;
确认号为 Ack = x + 1,表示收到客户端的序号 Seq 并将其值加 1 作为自己确认号 Ack 的值,随后服务器端进入 SYN-RECV 阶段。

③ 客户端接收到发送的 SYN + ACK 包后,明确了从客户端到服务器的数据传输是正常的,从而结束 SYN-SENT 阶段。并返回最后一段报文。其中:

标志位为 ACK,表示确认收到服务器端同意连接的信号;
序号为 Seq = x + 1,表示收到服务器端的确认号 Ack,并将其值作为自己的序号值;
确认号为 Ack= y + 1,表示收到服务器端序号 seq,并将其值加 1 作为自己的确认号 Ack 的值。
随后客户端进入 ESTABLISHED。
当服务器端收到来自客户端确认收到服务器数据的报文后,得知从服务器到客户端的数据传输是正常的,从而结束 SYN-RECV 阶段,进入 ESTABLISHED 阶段,从而完成三次握手。

四次挥手:
在这里插入图片描述
四次挥手即 TCP 连接的释放,这里假设客户端主动释放连接。在挥手之前主动释放连接的客户端结束 ESTABLISHED 阶段,随后开始四次挥手:

① 首先客户端向服务器发送一段 TCP 报文表明其想要释放 TCP 连接,其中:

标记位为 FIN,表示请求释放连接;
序号为 Seq = u;
随后客户端进入 FIN-WAIT-1 阶段,即半关闭阶段,并且停止向服务端发送通信数据。
② 服务器接收到客户端请求断开连接的 FIN 报文后,结束 ESTABLISHED 阶段,进入 CLOSE-WAIT 阶段并返回一段 TCP 报文,其中:

标记位为 ACK,表示接收到客户端释放连接的请求;
序号为 Seq = v;
确认号为 Ack = u + 1,表示是在收到客户端报文的基础上,将其序号值加 1 作为本段报文确认号 Ack 的值;
随后服务器开始准备释放服务器端到客户端方向上的连接。
客户端收到服务器发送过来的 TCP 报文后,确认服务器已经收到了客户端连接释放的请求,随后客户端结束 FIN-WAIT-1 阶段,进入 FIN-WAIT-2 阶段。

③ 服务器端在发出 ACK 确认报文后,服务器端会将遗留的待传数据传送给客户端,待传输完成后即经过 CLOSE-WAIT 阶段,便做好了释放服务器端到客户端的连接准备,再次向客户端发出一段 TCP 报文,其中:

标记位为 FIN 和 ACK,表示已经准备好释放连接了;
序号为 Seq = w;
确认号 Ack = u + 1,表示是在收到客户端报文的基础上,将其序号 Seq 的值加 1 作为本段报文确认号 Ack 的值。
随后服务器端结束 CLOSE-WAIT 阶段,进入 LAST-ACK 阶段。并且停止向客户端发送数据。

④ 客户端收到从服务器发来的 TCP 报文,确认了服务器已经做好释放连接的准备,于是结束 FIN-WAIT-2 阶段,进入 TIME-WAIT 阶段,并向服务器发送一段报文,其中:

标记位为 ACK,表示接收到服务器准备好释放连接的信号;
序号为 Seq= u + 1,表示是在已收到服务器报文的基础上,将其确认号 Ack 值作为本段序号的值;
确认号为 Ack= w + 1,表示是在收到了服务器报文的基础上,将其序号 Seq 的值作为本段报文确认号的值。
随后客户端开始在 TIME-WAIT 阶段等待 2 MSL。服务器端收到从客户端发出的 TCP 报文之后结束 LAST-ACK 阶段,进入 CLOSED 阶段。由此正式确认关闭服务器端到客户端方向上的连接。客户端等待完 2 MSL 之后,结束 TIME-WAIT 阶段,进入 CLOSED 阶段,由此完成「四次挥手」。

如果三次握手的时候每次握手信息对方没有收到回怎么样

一般来说都是服务端被动监听,客户端主动发起连接请求。

server未收到第一次握手信息:客户端通过connect()系统调用发起建立连接请求,如若由于某种原因server没有收到请求建立连接报文(SYN同步报文),那么很显然server端什么也不会发生(因为server对这一切毫不知情),下面讨论下client端做出的反应:

1.1 如果client发送的SYN报文或者server回应的确认报文在通信链路中丢失,客户端隔了一段时间t1没有收到回应,那么会隔更长的一段时间t2(一般为2t1)重新发送SYN同步报文,若仍没有回应,重复上述过程直至发送次数超过限制tcp_syn_retries。超过这个限制后接收不到回应,connect()系统调用会返回-1,并设置errno为ETIMEOUT。

1.2 如果是提供给client的server端地址是错误的或者按照client端的路由转发表根本到达不了server,那么在通信网络的某个路由器会返回一个“目的地不可达”的ICMP错误信息。client主机内核保存该错误信息,尝试按照上面所述的时间间隔继续发送SYN报文,同样的,超过一定限制后还没有收到响应,connect()系统调用会返回-1,并设置errno为EADDRNOTAVAIL。

这正体现了TCP可靠性的一部分原因:为报文设立序号、通过确认号实现超时重传机制。

client未收到第二次握手信息:server通过accept()系统调用阻塞监听连接,直至client-server双方连接完全建立才会返回。如果client发送的SYN报文server收到,此时server端内核会对其回应一个ACK报文(同时也是SYN报文),但由于某种原因client没有接收到该报文,很显然此时client做出的反应如1.1所述进行超时重传,此处不再重复。下面讨论关于server端做出的反应,对于"client未收到第二次握手信息"这种情况,这里的讨论主体实际上是client,因为client未收到确认信息,会重新发送确认报文,而此时server只是阻塞在accpet()系统调用处等待client再次发送SYN报文。

server未收到第三次握手信息: server端未收到client发来的ACK报文,同样的采取上述超时重传机制,如果重传次数超过tcp_synack_retries仍没有回应,那么accept()系统调用返回-1,server端连接建立失败。值得一提的是,client端单方面的建立连接成功了,即client可以向server端发送数据,但是server端accept()系统调用已经返回,server并没有在进行监听,而TCP协议是一个可靠全双工协议,因此server接收到来自client端发送来的数据时会发送RST报文给client。(复位client,消除client单方面建立连接的状态

为什么要进行三次握手?两次握手可以吗?

如果采用两次的话,会出现下面这种情况。比如是A机要连到B机,结果发送的连接信息由于某种原因没有到达B机;于是,A机又发了一次,结果这次B收到了,于是就发信息回来,两机就连接。
传完东西后,断开。结果这时候,原先没有到达的连接信息突然又传到了B机,于是B机发信息给A,然后B机就以为和A连上了,这个时候B机就在等待A传东西过去。

第 2 次握手传回了 ACK,为什么还要传回 SYN

接收端传回发送端所发送的ACK是为了告诉客户端,我接收到的信息确实就是你所发送的信号了,这表明从客户端到服务端的通信是正常的。而回传SYN则是为了建立并确认从服务端到客户端的通信。”

为什么要四次挥手?

那四次分手又是为何呢?TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。如果要正确的理解四次分手的原理,就需要了解四次分手过程中的状态变化。

FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。(主动方)
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你(ACK信息),稍后再关闭连接。(主动方)
CLOSE_WAIT:这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。(被动方)
LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。(被动方)
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FINWAIT1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(主动方)
CLOSED: 表示连接中断。

CLOSE-WAIT 和 TIME-WAIT 的状态和意义

TIME_WAIT 状态会导致什么问题,怎么解决

TIME-WAIT 为什么是 2MSL(报文最大生存期)

为了保证客户端发送的最后一个ACK报文段能够到达服务器。这个ACK报文段可能丢失,因而使在Last-ACK状态的服务器收不到对已发送的FIN+ACK报文段的确认。服务器就会超时重传这个报文段,而客户端就能在2MSL时间内收到这个重传的FIN-ACK报文段。接着客户端重传一个确认,重新启动2MSL计时器。最后客户端和服务器端都能正常进入到CLOSED状态。如果服务器端在TIME-WAIT状态下不等待一段时间,而是在发送完ACK报文段就立即释放连接,那么客户端就无法收到服务器重传的FIN_ACK报文段,因而也就不会再发送一个报文段,这样服务器就无法进入CLOSED状态。

有很多 TIME-WAIT 状态如何解决

有很多 CLOSE-WAIT 怎么解决

TCP 和 UDP 的区别

TCP向上层提供面向连接的可靠服务 ,UDP向上层提供无连接不可靠服务。
虽然 UDP 并没有 TCP 传输来的准确,但是也能在很多实时性要求高的地方有所作为
对数据准确性要求高,速度可以相对较慢的,可以选用TCP

TCP 协议中的定时器

重传计时器、坚持计时器、保活计时器、时间等待计时器

重传计时器
在TCP发送报文时创建,用来确认报文是否成功发送,超过预定时间,则重新发送。

坚持计时器
当发送端收到窗口大小为0的确认信号时,就启动了坚持计数器,如果坚持计数器的时间到达之后,还没有收到接收端发来的确认信号,就会主动发送一个特殊的报文端,叫做探测报文。探测报文只有一个字节的数据,它有一个序号,和普通报文不同,它的序号不需要被确认。探测报文是为了提醒接收端,刚刚给我发送的窗口大小已经丢了,要重新向我发送ACK确认信号,如果接收端没有回应,则需要重新发送一个探测报文,并将坚持计数器的时间加倍,直到增大到60s。在这之后,每隔60s就发送一个探测报文,直到窗口重新打开。

保活计时器
用来防止两个TCP之间的连接出现长时期的空闲。

 当client打开了server的连接,传送了很短时间的数据之后,就保持静默,可能会因为各种原因导致,但现在它确实处于了空闲状态。如果由于client出现故障,那么这个连接就一直处于打开状态。

 为了避免这种情况,引入了保活计时器。每当server收到了client发来的信息,就将计时器清零。如果server超过了保活计时器的时间仍没有收到任何消息,就会向client发送探测报文段,若发送了10个探测报文段之后仍没有反应,则认为client故障,server主动断开连接。

时间等待计时器
连接终止期间使用【TIME_WAIT】。

首先认识一个概念,MSL,报文最大生存时间。任何报文在网络上超过MSL之后,将被直接丢弃。

在TCP第三次挥手期间,客户端收到了服务器发来的FIN报文,之后客户端启动了TIME_WAIT计时器,时间设置为2MSL,并发送最后一个ACK。保证了2MSL时间内server可以收到最后一个ACK确认信号,同时保证了在之前发送的报文不会在连接关闭之后再次骚扰server,因为网络中的数据包到达目的地的时间是不确定的。
重传计时器 通常设置为 60s

坚持计时器 门限值60s

保活计时器 通常设置为2小时

时间等待计时器 通常设置为2MSL

TCP 是如何保证可靠性的

TCP协议保证数据传输可靠性的方式主要有:
校验和
序列号
确认应答
超时重传
连接管理
流量控制
拥塞控制

UDP 为什么是不可靠的?bind 和 connect 对于 UDP 的作用是什么

UDP协议
不保证消息交付:不确认,不重传,无超时
不保证交付顺序:不设置包序号,不重排,不会发生队首阻塞
不跟踪连接状态: 不必建立连接或重启状态机
不需要拥塞控制: 不内置客户端或网络反馈机制
1:UDP中可以使用connect系统调用

2:UDP中connect操作与TCP中connect操作有着本质区别。

TCP中调用connect会引起三次握手,client与server建立连结.UDP中调用connect内核仅仅把对端ip&port记录下来.

3:UDP中可以多次调用connect,TCP只能调用一次connect.

UDP多次调用connect有两种用途:1,指定一个新的ip&port连结. 2,断开和之前的ip&port的连结.

指定新连结,直接设置connect第二个参数即可.

断开连结,需要将connect第二个参数中的sin_family设置成 AF_UNSPEC即可.

4:UDP中使用connect可以提高效率.原因如下:

普通的UDP发送两个报文内核做了如下:#1:建立连结#2:发送报文#3:断开连结#4:建立连结#5:发送报文#6:断开连结

采用connect方式的UDP发送两个报文内核如下处理:#1:建立连结#2:发送报文#3:发送报文另外一点, 每次发送报文内核都由可能要做路由查询.

TCP 超时重传的原理

超时重传是指发送出去的数据包到接收到确认包之间的时间,如果超过了这个时间会被认为是丢包了,需要重传。

TCP 的停止等待协议是什么

在发送无差错的情况下,发送发每次向接收方发送一次分组,接收方就会向发送方发送一个确认分组,当发送方收到确认后即会发送下一个分组。

超时重传:发送方会内置一个超时计时器,时间略长于一个分组发送至接收方,接收方又将确认发送过来的时间,若发送方向接收方发送的数据丢失,计时器到时间则会使发送方重新发送分组直至收到确认。

确认丢失:若接收方发送的确认丢失了,发送方会超时重传同一个分组,接收方收到此重复的分组后将此丢弃并重新发送一次确认。

确认迟到:若接收方发送的确认由于路途过于遥远,而触发了发送方的超时重传后,接收方丢弃重复的分组再次发送确认,使得发送方收到了第二次的确认,但是此时第一次的确认又到了,发送方则会丢到重复的确认。

TCP 最大连接数限制

TCP 流量控制与拥塞控制

如果接收方滑动窗口满了,发送方会怎么做

  1. 只要收到了包,就会ACK。
  2. TCP在ACK的同时会带有window大小值,表示这边能接受的数据量。发送方会根据这个调整数据量。
  3. 接收方缓冲区满时,回给发送方的window值就是0。
  4. 发送方看到window为0的包,会启动一个定时器,隔一段时间发一个包试探。
  5. 一旦接收方缓冲区有足够空间了,就会给window赋上非0值。发送方就又开始发送了

TCP 拥塞控制采用的四种算法

慢开始和拥塞避免
快重传和快恢复

TCP 粘包问题

TCP 报文包含哪些信息

从tcp的作用出发就清晰了。

  1. tcp 要把报文从一个端发到另一个端,所以必须有 源端口,目标端口
    2 .tcp 要保证可靠性: 校验,滑动窗口,序号,确认号
  2. tcp 基于连接: 标志位
    4 tcp 帮忙分片: offset,标识

还有一些可选字段不重要
在这里插入图片描述

SYN FLOOD 是什么

为什么服务端易受到 SYN 攻击

高并发服务器客户端主动关闭连接和服务端主动关闭连接的区别

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值