计算机网络 | TCP 三次握手四次挥手 |半关闭连接

本来是不愿意写的,可是在实际场景,对具体的描述标志还是模糊不清,基础不扎实,就得承认!!!

TCP 连接建立需要解决三大问题:

  1. 知道双方存在
  2. 约定一些参数,如最大滑动窗口值、是否使用滑动窗口扩大选项、时间戳、服务质量等等
  3. 双方能够对运输实体资源(缓存大小、连接表中的项目)进行分配

三次握手

握手: TCP客户端和服务器之间进行交换三个TCP报文段

  1. 初始状态:两端的进程都处于关闭状态
  2. 服务器端创建传送控制块,用来存储TCP连接中的一些重要信息(TCP连接表、指向发送和接收缓存的指针、指向重传队列的指针、当前发送和接收序号等等),之后准本接收TCP客户进程的连接请求。TCP服务器处于监听状态 ,等待客户端进程的连接请求(TCP服务器是被动等待TCP客户进程的连接请求)(这又叫被动打开连接,不是主动建立连接的)
  3. TCP客户进程首先创建传输控制块 (请求发送和接收缓存的指针、指向重传队列的指针、当前的发送和接收序号)
  4. 开始第一次握手,TCP客户进程发送TCP请求报文段,进入同步已发送状态(SYN-SENT),发送的请求报文段中首部的同步位 (SYN = 1),序号字段(seq = x,作为TCP客户进程所选择的初始序号)(注意TCP规定,SYN被设置为1的报文段不能携带数据,但是要消耗一个序号**)(主动打开连接
  5. 第二次握手(前提是服务进程接收客户进程的连接请求),TCP服务进程向TCP客户进程发送连接请求确认报文段(进入同步已接收状态, 监听状态--> 同步已接收状态)(连接请求报文段中头部SYN = 1,ACK = 1, seq = y, ack = x + 1) (同步位SYN = 1,确认位ACK = 1,这可以确定这是连接请求确认报文段) 序号字段 seq = y(初始值设置为y,作为TCP服务器进程所选择的初始序号,确认字段ack = x + 1,这是对TCP客户进程所选择的初始序号的确认),注意,这次发送的报文段(第二次握手)也不能发送数据,同样消耗一个序号
  6. 第三次握手(前提是TCP客户进程收到TCP请求确认报文段),接着TCP客户进程向TCP服务进程发送一个普通 的TCP确认报文段。此时客户进程进入连接已建立状态 ,该发送的普通报文段中,确认位ACK = 1(这表明这是一个普通的TCP确认报文段),序号字段seq = x +1,确认字段ack = y +1(这是对TCP服务进程所选择的初始序号的确认)。(注意,这里的序号为x + 1 ,就是第一次握手发送的报文段是消耗了一个序号,然后TCP规定普通报文段是可以传输数据的,如果不携带数据这不消耗序号,在不携带数据的情况下,下一个数据报文段的序号仍然是x + 1)。TCP服务进程接收到该报文段后也进入了连接已建立状态
  7. 接下来就可以进行可靠的数据传输。

为什么还要发送一个普通的TCP确认报文段呢????===>能够两次握手建立连接???

特殊情境:TCP客户进程发送的请求报文段发送到了TCP服务端进程,但用了很长时间,所以会引发该报文段的超时重传,然后重传的报文段被TCP服务进程正常接收(注意后来发送的超时重传的报文段反而先被接收)然后地第二次握手。注意如果这是两次握手。然后TCP服务进程就进入了连接已建立状态(而不是三次握手进入同步已接收状态。这个时候TCP服务进程会等待TCP客户进程发送TCP连接请求确认报文段的普通确认报文段),第二次握手,没有给TCP发送普通 报文段,进入了连接已建立状态。此时两两可以开始传输数据。开始传输数据了哈,然后传输的数据很少,然后很快就断开连接,两端断开连接后,这时变态的事情就发生了,TCP服务线程接收到第一次发送的TCP连接请求报文段(TCP服务线程进入的连接已建立状态)。然后TCP服务线程肯定会发送确认报文段嘛,搞笑的事情就发生了,TCP客户线程就会莫名奇怪。明明断开连接之后,我啥也没干呀!!!(不理睬,关闭状态)

四次挥手

数据传输结束后,双方都可以释放连接

释放连接前的状态都是 连接已建立(EDTABLISHED)

  1. 假设是TCP客户进程的应用进程通知其主动关闭TCP连接。TCP客户进程发送TCP连接释放报文段,接着TCP客户进程主动关闭状态,进入终止等待1状态(FIN-WAIT-1),该发送的连接释放报文段中的头部终止位FIN = 1,确认位ACK = 1。可以通过这些头部字段信息判定这是TCP连接释放报文段(因为有时候抓包,需要确认什么什么是什么什么包)。同时,对之前收到的报文段确认 seq = u,ack = v。(u -1 , v - 1 分别表示什么 可以参照TCP三次握手)(注意:TCP规定终止位FIN = 1的报文段即使不携带数据,也要消耗一个序号
  2. TCP服务进接收到发送的连接释放报文段后,会发送一个普通的TCP确认报文段,ACK = 1,seq = v , ack = u + 1(还是解释以下吧,seq = TCP服务进程之前已经传送的数据的最后一个字节序号加1),--->关闭等待状态 (CLOSE-WAIT),同时TCP服务进程通知高层应用进程,TCP客户进程要和我们断开TCP连接,请做好断开连接的准备。注意这时,TCP客户进程到TCP服务进程这个方向(--->)的连接就释放了。这时的TCP连接也叫做半关闭状态 。(怎么个半关闭呢?TCP客户进程已经没有发数据给TCP服务进程,但是要注意这个时候TCP服务进程还可以发送数据给TCP客户进程。虽然在TCP服务这边,服务进程已经传达断开消息给高层应用了,但是这段时间内,高层应用是可以继续发送消息的,简言之TCP服务线程可以发送数据给TCP客户线程,并且TCP客户线程是可以接受到发送过来的数据)。TCP客户进程接收到TCP确认报文段后就进入终止等待2状态(FIN-WAIT-2)
  3. TCP服务应用进程知晓后,也就会通知TCP服务进程没有数据要发送,接着TCP服务进程就会发送连接释放报文段(报文段首部FIN = 1 ACK = 1 ,seq = w , ack = u + 1 所以期间发送的报文段次数为w - v 注意 u + 1 是对之前收到的TCP连接释放报文段的重复确认。也就是TCP客户线程第一次发送的报文段的确认)给TCP客户线程。TCP服务这边是被动关闭连接,TCP服务线程发送TCP连接释放报文段后,其状态---->最后确认 (LAST-ACK)
  4. TCP客户线程 接收到发送的报文段后,紧接着发送TCP普通确认报文段 ACK = 1, seq = u + 1, ack = w + 1。之后TCP客户端进入时间等待状态 发送的报文段消耗一个序号。TCP 服务线程接收到该报文段后进入关闭状态(CLOSED),注意TCP客户线程需要经过2MSL时间后才能进入关闭状态。

解释:MSL 最长报文段寿命 RFC793建议为2分钟
思考为什么TCP客户线要经历2MSL的时间自动关闭连接,置为关闭状态呢?

分析,如果TCP客户端发送TCP普通确认报文段后直接置为关闭状态,但是这个报文段很遗憾没有发送成功,在半路丢失。在TCP服务线程触发超时重传,又进行第三次挥手。但是TCP客户线程已经下线了,怎么也连不上,那这就是没有关闭成功。(怎么算的2MSL ??TCP客户线程 发送过去,触发超时,TCP服务线程发送报文段,两倍2MSL)

引申 保活计时器

相关推荐
sakoba4 分钟前
Docker学习其二(容器卷,Docker网络,Compose)
运维·网络·学习·docker·容器·基础
惜.己2 小时前
appium中urllib3.exceptions.LocationValueError: No host specified. 的错误解决办法
网络·appium
吉凶以情迁2 小时前
window服务相关问题探索 go语言服务开发探索调试
linux·服务器·开发语言·网络·golang
专注VB编程开发20年2 小时前
UDP受限广播地址255.255.255.255的通信机制详解
网络·udp·智能路由器
189228048613 小时前
NX947NX955美光固态闪存NX962NX966
大数据·服务器·网络·人工智能·科技
Sadsvit4 小时前
Linux 进程管理与计划任务
linux·服务器·网络
一碗白开水一5 小时前
【模型细节】FPN经典网络模型 (Feature Pyramid Networks)详解及其变形优化
网络·人工智能·pytorch·深度学习·计算机视觉
什么都想学的阿超5 小时前
【网络与爬虫 38】Apify全栈指南:从0到1构建企业级自动化爬虫平台
网络·爬虫·自动化
D-海漠6 小时前
安全光幕Muting功能程序逻辑设计
服务器·网络·人工智能
都给我7 小时前
可计算存储(Computational Storage)与DPU(Data Processing Unit)的技术特点对比及实际应用场景分析
运维·服务器·网络·云计算