2.TCP三次握手、四次挥手

1. TCP三次握手

  • 第一次握手(SYN)
  1. 客户端发送SYN:客户端选择一个初始序列号seq=x,发送SYN包(包含序列号seq=x)给服务器。表示客户端请求建立连接。
  2. 客户端状态:客户端进入SYN_SEND状态,等待服务器响应。
  • 第二次握手(SYN-ACK)
  1. 服务器接收到并响应SYN:服务器收到客户端的SYN包后,选择一个初始序列号seq=y,并发送一个SYN-ACK包(包含服务器的序列号seq=y、对客户端的确认序列号ack=x+1)给客户端。
  2. 服务器状态:服务器进入SYN_RECEIVED状态,等待客户端确认。
  • 第三次握手(ACK)
  1. 客户端确认连接:客户端收到服务器的SYN-ACK包后,发送一个ACK包(包含客户端的序列号seq=x+1、对服务器的确认序列号ack=y+1)给服务器。表示客户端已接收到了服务器的SYN包。
  2. 双方状态:都进入ESTABLISHED状态,表示连接成功,可以进行数据传输。

1.1 三次握手中如果数据发送失败,如何设计处理?

  • 设计重试机制:
  1. 在客户端发送一个数据包后,在设定的超时时间内未收到服务端的确认应答包。客户端立刻重发数据包。
  2. 重试次数设定一个上限,若超过上限,则认定服务端已经断联。
  • 设计超时机制:
  1. 设定一个合理的超时时间,例如2秒,客户端在发送SYN包后等待这个时间,若超过这个时间立刻重发数据包。

1.2 第一次握手可以传输数据吗?

  • 不可以传输数据,原因是:
  • 连接未建立,服务器还未确认客户端的连接请求。客户端无法确认服务器是否收到SYN包,所以无法保证数据传输是可靠的。一次握手就传输数据可能导致旧的连接请求被误认为新的连接,造成数据传输混乱。

1.3 为什么要三次握手?不能两次吗?

原因: 三次握手确保客户端和服务端都知道对方的接收、发送能力是正常的。避免旧的历史连接请求被误认为是新的连接请求。

  • 避免历史连接请求的影响:若使用两次握手,旧的连接请求(可能因网络延迟而滞留的SYN包)被误认为是新的连接请求,导致连接状态不一致。
  • 双方确认机制不足:两次握手无法保证双方确认了连接的存在。(第一次握手, 接收方知道发送方的发送能力正常。第二次握手 ,发送方知道接收方的发送、接收能力正常。第三次握手 ,接收方知道发送方的接收能力正常)

2. TCP四次挥手

  • 第一次挥手(FIN)
  1. 客户端发送FIN:客户端选择一个序列号seq=x,发送FIN包给服务器。表示客户端已经没有数据要发送,准备关闭连接。
  2. 客户端状态:客户端进入FIN_WAIT_1状态,等待服务器响应。
  • 第二次挥手(ACK)
  1. 服务器发送ACK:服务器收到FIN包后,发送一个ACK包(包含服务器的序列号seq=y、对客户端的确认序列号ack=x+1)。表示已经接收到客户端的关闭请求。
  2. 服务器状态:服务器进入CLOSE_WAIT状态,表示服务器仍可能有数据要发送,发送完后发送FIN包。
  3. 客户端状态:客户端进入FIN_WAIT_2状态,等待服务器响应关闭请求。
  • 第三次挥手(FIN)
  1. 服务器发送FIN:服务器完成最后的数据发送后,发送FIN包(包含服务器的序列号seq=y、对客户端的确认序列号ack=x+1)和ACK报文。表示服务器也准备关闭连接。
  2. 服务器状态:服务器进入LAST_ACK状态。等待客户端确认。
  • 第四次挥手(ACK)
  1. 客户端发送ACK:客户端收到FIN包后,发送ACK包(包含客户端的序列号seq=x+1、对服务器的确认序列号ack=y+1)。表示确认关闭连接。
  2. 客户端状态:客户端进入TIME_WAIT状态,等待2MSL(最大报文生存时间)后关闭连接进入CLOSED状态。
  3. 服务器状态:服务器收到ACK包后,进入CLOSED状态。

2.1 挥手时的 CLOSE_WAIT阶段还能收到报文吗?

  • CLOSE_WAIT状态:表示一方已收到对方的FIN包,并发送了ACK包,等待自身处理好未发送的包后关闭连接。在CLOSE_WAIT状态仍然可以接收数据,直到接收方的状态为CLOSED停止接收。

2.2 为什么连接需要三次握手?关闭需要四次挥手?

  • 三次握手的原因:
  1. 防止重复连接:通过三次握手可以让双方都确认对方准备好了,避免历史连接请求影响当前连接。
  2. 保证双方都可发送和接收:保证双方都能确认对方的接收和发送能力是正常的。
  • 四次挥手的原因:
  1. 半关闭状态:TCP连接是全双工的,双方都可独立关闭自己的发送和接收通道。四次挥手可以实现这种半关闭状态,双方都能完成各自的数据传输。
  2. 可靠释放资源:通过四次挥手,确保双方都能可靠的释放掉连接资源,避免重复释放或一方释放,另一方还在连接状态无法释放。

2.3 为什么客户端的TIME_WAIT状态必须要等待2MSL?

  • MSL:是一个TCP报文段在网络中可以存活的最长时间。
  • 必须要等待2MSL的原因:

1)确保被动关闭方收到ACK:

  • 当主动关闭方发送最后一个ACK报文时,ACK报文段可能会丢失。被动关闭方没有收到这个ACK报文,就会重发FIN报文。
  • 主动关闭方必须等待一段时间,以确保他能收到可能重发的FIN报文,并再次发送ACK报文。
  • 如果没有等待2MSL,主动关闭方可能会在被动方发送FIN报文前关闭,导致被动关闭方无法关闭连接。

2)确保旧的报文段在网络中消失:

  • 在2MSL时间内,网络中所有旧的、重复的报文都超时被弃用。确保下一次新的连接不会收到前一个连接的旧报文段,避免数据混乱和连接错误。

3. TCP和UDP的头部

  • TCP头部:
  1. 源端口:发送方的端口号。
  2. 目的端口:接收方的端口号。
  3. 序列号:用于标识发送的数据字节流的顺序。
  4. 确认应答号:用于确认收到的数据字节的下一个序列号。
  5. 数据偏移:表示TCP的头部。
  6. 保留:保留位,未使用。
  7. 控制标志:包括URG、ACK、PSH、PST、SYN、FIN六个控制位。
  8. 窗口大小:接收窗口的大小,用于流量控制。
  9. 校验和:用于校验头部和数据部分的完整性。
  10. 紧急指针:指示紧急数据的结束位置。
  11. 选项:可选字段,长度可变。
  • UDP头部:
  1. 源端口:发送方的端口号。
  2. 目的端口:接收方的端口号。
  3. 长度:UDP头部和数据的总长度,以字节为单位。
  4. 校验和:用于校验头部和数据部分的完整性。

4.TCP可靠性及相关问题

4.1 TCP流量控制

定义:TCP的流量控制是通过滑动窗口实现的,确保发送方不会淹没接收方的处理能力。滑动窗口机制由发送窗口和接收窗口控制。

  • 发送窗口 :发送方维护的流量控制边界,用于限制 "已发送但未收到确认" 的数据总量。它的范围由两部分决定:
  1. 已发送但未被接收方确认的数据。
  2. 接收方通过 TCP 报文 "窗口字段" 告知的当前未发送但可以发送的最大数据量。
  • 接收窗口 :接收方维护的流量控制边界,用于限制 "已接收但未提交给应用层处理" 的数据总量。它的范围由两部分决定:
  1. 已接收但未处理的数据(暂存于接收缓存)。
  2. 接收方自身缓存剩余空间对应的当前未接收但可接收的最大数据量。
  • 窗口大小的控制逻辑
  1. 接收方会在每个 TCP 确认报文(ACK)中,将当前接收窗口的剩余可用大小告知发送方;发送方则根据这个值动态调整自己的发送窗口上限,实现双向流量控制。

4.2 TCP拥塞控制

定义:TCP的拥塞控制通过慢启动、拥塞避免、快重传、快恢复来防止网络拥塞。

  • 慢启动:
  1. 初始阶段:当连接刚建立,拥塞窗口从1开始,慢启动阈值通常未64。
  2. 指数增长:每收到一个ACK,拥塞窗口加倍,直到达到慢启动阈值。
  • 拥塞避免:
  1. 达到阈值:当拥塞窗口达到慢启动阈值,进入拥塞避免状态。
  2. 线性增长:每收到一个ACK,拥塞窗口增加1,避免网络拥塞。
  • 快重传:

检测重复ACK:如果发送方收到三个重复的ACK,立刻重传丢失的数据包。

  • 快恢复:

恢复拥塞窗口:重传丢失的包后,拥塞窗口恢复到慢启动的阈值一半,避免拥塞窗口重 置为1。

4.3 超时重传如何实现?超时重传时间如何确定?

  • 超时重传:在TCP协议中,如果发送方在预定的时间内没有收到接收方的确认(ACK),则认为数据包丢失,立刻重传丢失包。
  • 超时重传的时间(RTO):超时重传的时间是根据来回往返时间(RTT)来决定的,通过动态调整RTO,TCP能够适应网络状况,确保可靠传输。
  • RTO的计算:
  1. SRTT:使用加权平均算法计算平滑RTT的估计值。
  2. RTT方差:计算RTT的变化幅度。
  3. 通过SRTT和RTT方差计算超时重传时间(RTO)。

4.4 两台服务器将如何建立多条TCP连接?

  • 使用不同端口号或同一端口号的多个套接字实现。每个TCP连接都是由四元组(源IP、目标IP、源端口号、目的端口号)组成,只要改变其中一个就可以建立新的连接。

4.5 滑动窗口过大会怎么样?滑动窗口过小会怎么样?

  • 滑动窗口过大:
  1. 优点:在高带宽、低延迟的网络环境下,较大的滑动窗口可以允许发送方再不等待ACK确认的情况下发送更多数据,充分利用带宽,减少传输时间。
  2. 缺点:在高延迟或高丢包的网络环境下,较大的滑动窗口可能会导致大量未确认数据堆积,一旦发送丢包或错误,重传的数据量大,浪费带宽,可能导致网络拥塞。
  • 滑动窗口过小:
  1. 优点:在高延迟或高丢包的网络环境下,较小的滑动窗口可以限制未确认数据的数量,减少重传的数据量,降低网络拥塞的风险。
  2. 缺点:在高带宽、低延迟的网络环境下,较小的滑动窗口可以限制发送方的数据传输速率,频繁等待ACK确认,导致带宽利用率低,传输效率下降。

5.TCP的nagle算法?nagle算法会带来什么坏处?

  • nagle算法的目的:
  1. 减小小包:通过将小数据包合并成大包发送,减少网络中小包的数量。
  2. 提高效率:减少每个包的协议开销,提高传输效率。
  • nagle的工作原理:当发送方有小数据包需要发送时,如果前一个数据包的ACK未收到,新的小数据包会被缓冲,等待前一个包的ACK到达或缓冲区累计足够大的数据量再发送。
  • 坏处是增加延迟:数据包不能够立即发送出,需要在等待前一个包ACK到达时,进行数据包累积。

6.KCP是什么

  • 基于UDP:KCP是在UDP协议之上实现的,利用UDP的简单和快速传输特点,同时引入了TCP的一些可靠传输机制。
  • 目标:通过减少延迟和提高传输速率,为实时应用(在线游戏、实时视频等)提供更好的传输性能。

7. 如何保证UDP的帧与帧间的有序性

  • 序列号:
  1. 发送方:在发送数据包时,为每个数据包添加一个唯一的序列号。序列号从0开始,每发送一个数据包,序列号加1。
  2. 接收方:在接收数据包时,检查序列号,确保数据包的顺序。如果正确按顺序到达,则将其交给应用层处理。若数据包乱序到达,则交给重排序缓冲区,等待缺失包到达后,按序处理。
  • 重排序缓冲区:

接收方:维护一个重排序缓冲区,用于缓存乱序到达的数据包。接收方会检查数据包的 序列号,将其插入到正确的位置。如果发现有缺失,则等待缺失包到达在按序处理。

  • ACK确认机制:

接收方:在接收到数据包后,发送一个ACK确认包给发送方,包含已经成功接收的最高 序列号。发送方根据ACK确认包判断哪些包被接收,那些包需要重传。

  • 丢包重传机制:

发送方:如果在一定时间内没有接收到接收方的ACK确认包,则认为该数据包已丢失, 发送方立刻重新发送丢失的数据包。

8. 长连接如何维持的

  • 定时发送心跳包:设置定时器,定期发送心跳包,保证连接活跃。
  • 连接超时检测:设置合理的超时时间,检测连接状态,及时进行重连操作。
  • 资源管理:确保系统资源合理分配,避免长时间保持大量连接导致资源耗尽。

9.linux内核收包流程

  1. 网卡接收数据包:网卡接收到从网络传来的数据包,并将其存储在网卡的接收缓冲区中。
  2. DMA传输:网卡通过DMA将数据包直接传输到系统内存中,避免CPU参与数据传输,提高效率。
  3. 中断通知:网卡通过PCle总线生成硬件中断,通知CPU有数据包到达,CPU通过桥接/内存控制器接收中断信号。
  4. 软中断通知:CPU响应中断,执行硬件中断处理程序,硬件中断处理程序触发软中断,软中断继续处理数据包。
  5. 内核网络协议栈处理:软中断处理程序将数据包从缓冲区中取出,保存到skb(socket buffer)中。
  6. 数据包队列:内核网络协议栈进一步处理数据包,将其放入对应socket的接收队列中(data被放到socket的接收队列中)。
  7. 唤醒用户进程:内核唤醒等待数据的用户进程,用户进程从socket队列中读取数据,进行数据处理。

10.本机向本机发送请求,IP填127.0.0.1和网卡ip地址有区别吗?

  • 127.0.0.1(本地回环地址):数据包在内核网络栈中被处理,经过回环接口,不会通过物理网卡发送。用于测试和本地通信。

发送本地回环地址后的流程:

  1. 回环接口:当应用程序使用127.0.0.1发送请求时,数据包会被路由到回环接口。回环接口是在软件层面模拟的网络接口,专用于本地通信。
  2. 内核处理:数据包不会离开内核网络栈,而是直接在内核中被处理并返回发送方。数据包不经过物理网卡,不消耗网络带宽。
  • 网卡IP地址(本机实际的IP地址):数据包通过内核网络栈被处理,并经过物理网卡发送和接收,走完整的网络栈路径。用于正常的网络通信。

发送网卡ip地址的流程:

  1. 物理网卡:当应用程序使用本机的实际ip地址发送请求时,数据包会被路由到物理网卡,物理网卡根据MAC地址处理数据包,经过物理网络接口发送和接收。
  2. 完整的网络栈路径:数据包会走完完整的网络栈路径,包括物理层、数据链路层和网络层。数据包会真正的经过物理网卡,可能在网络上产生负载。

11. TCP粘包如何解决?

  • TCP粘包:由于TCP是面向流传输的协议,发送的数据没有边界,接收方可能在一次读取操作中接收到多个发送方的数据包,导致数据粘在一起。
  • 解决的三种方法:
  1. 定长消息:每个消息固定长度,接收方按固定长度读取数据。
  2. 分隔符:在每个消息之间添加特殊字符作为分隔符,接收方按分隔符拆分数据。
  3. 消息头标识长度:在每个消息前添加一个消息头,消息头包含该消息的长度,接收方根据长度读取完整消息。
相关推荐
紫色的路2 小时前
TCP消息边界处理的精妙算法
c++·网络协议·tcp/ip·算法
知乎的哥廷根数学学派2 小时前
基于高阶统计量引导的小波自适应块阈值地震信号降噪算法(MATLAB)
网络·人工智能·pytorch·深度学习·算法·机器学习·matlab
DeepFlow 零侵扰全栈可观测2 小时前
DeepFlow 实践:利用 eBPF 实现覆盖从网关到数据库的全栈分布式追踪
网络·分布式·云原生·云计算
松涛和鸣2 小时前
51、51单片机
c语言·网络·单片机·嵌入式硬件·tcp/ip·51单片机
CHENKONG_CK2 小时前
晨控CK-FR09EIP与汇川H5U系列PLC配置EtherNet/IP通讯连接手册
网络·网络协议·自动化·rfid
上海云盾安全满满2 小时前
面对T级大流量攻击,业务如何确保稳定可用
网络
古城小栈2 小时前
Rust 异步、并发 一文全解
网络·rust
小码吃趴菜2 小时前
tcp连结建立与断开(三握手四挥手)
服务器·网络·tcp/ip
WTCLLB2 小时前
cmd-set-ip
网络·windows