计算机网络传输协议TCP三次握手与四次挥手原理

目录
  • TCP三次握手四次挥手
    • 服务器状态转换
    • 客户端状态转换
    • TCP状态转换图
  • TCP中常见的面试题
    • 为什么是三次握手,不是一次或者两次
    • 为什么是三次握手,四次挥手
    • 如果已经建立了连接,但是客户端突然出现故障了怎么办?
    • 为什么会有TIME_WAIT状态
      • 我们来想一想,为什么TIME_WAIT的时间是2MSL
    • 解决TIME_WAIT状态引起的bind失败的方法

TCP三次握手四次挥手

我们之前在 传输层协议TCP与UDP中详细介绍了UDP协议和TCP协议格式以及他们各自的特点,我们知道TCP协议是面向连接的,那面向连接就得需要做建立连接,维护连接,断开连接这些工作。

服务器状态转换

[CLOSED->LISTEN] 服务器调用listen后就进入LISTEN状态,等待客户端向自己发起连接

[LISTEN->SYN_RCVD] 一旦监听到连接请求(同步报文段),就会将该连接放入内核中维护的连接等待队列中,并向客户端发送SYN+ACK报文确认已收到看客户端的连接请求

[SYN_RCVD->ESTABLISHED] 服务器一旦收到了客户端的确认报文,就进入ESTABLISHED状态,就可以进行读写数据了

[ESTABLISHED->CLOSE_WAIT] 当客户端主动关闭连接(调用close),服务器收到客户端发送的结束报文段FIN,服务器向客户端返回确认收到关闭连接的报文后,就会进入CLOSE_WAIT

[CLOSE_WAIT->LAST_ACK] 当服务器进入CLOSE_WAIT状态时,说明服务器已经开始准备关闭连接(但是需要先处理完之前的数据),当服务器真正调用close关闭连接时,会向客户端发送FIN报文,自己则进入LAST_ACK状态,等待最后一个ACK的到来(这里的ACK是指客户端对于服务器发送的FIN的响应报文)

[LAST_ACK->CLOSED] 服务器收到了客户端对FIN报文的响应ACK,至此服务器关闭连接成功

客户端状态转换

[CLOSED->SYN_SEND] 客户端调用connect,向服务器发送同步报文段,表示想与服务器建立连接,自己进入SYN_SEND状态等待服务器的响应

[SYN_SEND->ESTABLISHED] connect调用成功,客户端收到服务器的响应报文ACK,进入ESTABLISHED状态,可以读写数据

[ESTABLISHED->FIN_WIAT_1] 客户端主动调用close,向服务器发送结束报文段,自己进入FIN_WAIT_1状态,等待服务器的响应

[FIN_WAIT_1->FIN_WAIT_2]客户端收到服务器对结束报文段的确认,则进入FIN_WAIT_2状态,开始等待服务器的结束报文段

[FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出对服务器发送的结束报文的的响应 LAST_ACK;

[TIME_WAIT -> CLOSED] 客户端要等待一个2MSL(Max Segment Life, 报文最大生存时间)的时间, 才会进入CLOSED状态(因为要防止服务器没有收到LASK_ACK,需要进行重发的情况).

TCP状态转换图

TCP中常见的面试题

为什么是三次握手,不是一次或者两次

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

  • 现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发送了确认应答分组。
    按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。
    可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。
    在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
  • 两次握手还可能造成服务器资源的浪费,怎么说呢,再举个栗子,假设今天C向S发送了一个连接请求,并等待S的响应,S给C发送ACK之后,就认为连接已经建立,我们知道连接建立之后是需要维护这个连接的,此时S的操作系统就需要分配资源和空间来维护这个连接,那假设S给C的响应丢失了,C并未收到响应则认为连接没有建立成功,不能正常通信,此时S维护的连接就是一个失败的连接,不能成功通信,那假设今天由100万个客户端向S这个服务器发送连接请求,结果都没有收到响应,此时S就维护了100万个无用的连接,浪费服务器的资源

为什么是三次握手,四次挥手

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。

但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。

只有等到Server端所有的报文都发送完了,所有的数据也处理完了之后,Server端才能发送FIN报文表示自己能够断开连接,因此不能一起发送。故需要四步握手。

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

答:TCP连接是有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。

服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。

若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

为什么会有TIME_WAIT状态

现在做一个测试,首先启动server,然后启动client,然后用Ctrl-C使server终止,这时马上再运行server, 结果是:

这是因为,虽然server的应用程序终止了,但TCP协议层的连接并没有完全断开,因此不能再次监 听同样的server端口.我们用netstat命令查看一下:

  • TCP协议规定,主动关闭连接的一方要处于TIME_ WAIT状态,等待两个MSL(maximum segment lifetime)的时间后才能回到CLOSED状态.
  • 我们使用Ctrl-C终止了server, 所以server是主动关闭连接的一方, 在TIME_WAIT期间仍然不能再次监听同样的server端口;
  • MSL在RFC1122中规定为两分钟,但是各操作系统的实现不同, 在Centos7上默认配置的值是60s;
  • 可以通过 cat /proc/sys/net/ipv4/tcp_fin_timeout 查看msl的值

我们来想一想,为什么TIME_WAIT的时间是2MSL

MSL是TCP报文的最大生存时间, 因此TIME_WAIT持续存在2MSL的话就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启, 可能会收到来自上一个进程的迟到的数据, 但是这种数据很可能是错误的);

同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失, 那么服务器会再重发一个FIN. 这时虽然客户端的进程不在了, 但是TCP连接还在, 仍然可以重发LAST_ACK);

解决TIME_WAIT状态引起的bind失败的方法

  • 在server的TCP连接没有完全断开之前不允许重新监听, 某些情况下可能是不合理的
  • 服务器需要处理非常大量的客户端的连接(每个连接的生存时间可能很短, 但是每秒都有很大数量的客户端来请求).
  • 这个时候如果由服务器端主动关闭连接(比如某些客户端不活跃, 就需要被服务器端主动清理掉), 就会产生大量TIME_WAIT连接.
  • 由于我们的请求量很大, 就可能导致TIME_WAIT的连接数很多, 每个连接都会占用一个通信五元组(源ip,源端口, 目的ip, 目的端口, 协议). 其中服务器的ip和端口和协议是固定的. 如果新来的客户端连接的ip和端口号和TIME_WAIT占用的链接重复了,就会出现问题.
  • 使用setsockopt() 设置socket描述符的 选项SO_REUSEADDR为1, 表示允许创建端口号相同但IP地址不同的多个socket描述符

  • 加上了setsockopt之后,ctrl+c终止服务器之后也可以马上启动服务器

以上就是计算机网络传输协议TCP三次握手与四次挥手原理的详细内容,更多关于TCP三次握手与四次挥手的资料请关注我们其它相关文章!

(0)

相关推荐

  • TCP的三次握手与四次挥手详细介绍

    TCP的三次握手与四次挥手详细介绍 为什么是三次握手? 目的:防止已失效的连接请求又传到了服务器端. 场景(A为客户,B为服务器):A向B发送一个请求连接报文,但是这个报文在网络中阻塞了,并没有传到B.所以B也无法向A发送确认报文,在A的重传计时器到达之后,A再次向B发送请求连接报文,这个报文B收到了,并且向A做出应答,建立连接,传输数据.数据传输完后,关闭连接.问题来了,就在B关闭连接之后,A第一次发送的请求连接报文到了(这个报文是已经失效的),B以为A要再次创建一个新连接,于是向A发送确认报

  • TCP/IP协议中三次握手四次挥手的原理及流程分析

    当初学的是通信专业,毕业以后,同学们各奔东西,去追逐自己的梦想,奔波于大大小小的工地之间.哈哈,开个玩笑,也有厉害的,进了某某研究所,嗯?他爸不是所长,内心不要太阴暗.记得有一门十分高大上的课程,名字叫做计算机网络(大概是这个名字吧).里面有一个关于握手的概念,现在温习一下. 先来看看原理图: TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接.在TCP/IP协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的.三次握手的目的是同步连接双方的序列

  • 两张动图--带你搞懂TCP的三次握手与四次挥手

    目录 TCP的概述 TCP报文首部 TCP连接的建立(三次握手) 什么TCP客户端最后还要发送一次确认呢? TCP连接的释放(四次挥手) 为什么客户端最后还要等待2MSL? 如果已经建立了连接,但是客户端突然出现故障了怎么办? 总结 背景描述 通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之间的通信.但是这并不具体,因为,真正进行通信的实体是在主机中的进程,是一个主机中的一个进程与另外一个主机中的一个进程在交换数据.IP协议虽然能把数据报文送到目的主机,但是并没有交付给主

  • 计算机网络传输协议TCP三次握手与四次挥手原理

    目录 TCP三次握手四次挥手 服务器状态转换 客户端状态转换 TCP状态转换图 TCP中常见的面试题 为什么是三次握手,不是一次或者两次 为什么是三次握手,四次挥手 如果已经建立了连接,但是客户端突然出现故障了怎么办? 为什么会有TIME_WAIT状态 我们来想一想,为什么TIME_WAIT的时间是2MSL 解决TIME_WAIT状态引起的bind失败的方法 TCP三次握手四次挥手 我们之前在 传输层协议TCP与UDP中详细介绍了UDP协议和TCP协议格式以及他们各自的特点,我们知道TCP协议是

  • Wireshark基本介绍和学习TCP三次握手

    这篇文章介绍另一个好用的抓包工具wireshark, 用来获取网络数据封包,包括http,TCP,UDP,等网络协议包. 记得大学的时候就学习过TCP的三次握手协议,那时候只是知道,虽然在书上看过很多TCP和UDP的资料,但是从来没有真正见过这些数据包, 老是感觉在云上飘一样,学得不踏实.有了wireshark就能截获这些网络数据包,可以清晰的看到数据包中的每一个字段.更能加深我们对网络协议的理解. 对我而言, wireshark 是学习网络协议最好的工具. 阅读目录 wireshark介绍 w

  • 详解PHP Swoole与TCP三次握手

    握手常见问题 1.连接拒绝 2.Operation now in progress 多是因为丢包.错误ip.backlog满了&阻塞&tcp_abort_on_overflow=0 3.min(maxconn, backlog) ss -lt 连接拒绝 在TCP三次握手的时候,客户端发送SYN这个包给服务端,服务端不接受这个请求,操作系统直接返回了一个RST的包,来拒绝连接的请求. 最常见的情况就是客户端去请求某个服务器,服务端没有绑定对应的端口. 测试代码如下,服务端代码: <?p

  • TCP三次握手及原理

    TCP/IP是很多的不同的协议组成,实际上是一个协议组,TCP用户数据报表协议(也称作TCP传输控制协议,Transport Control Protocol.可靠的主机到主机层协议.这里要先强调一下,传输控制协议是OSI网络的第四层的叫法,TCP传输控制协议是TCP/IP传输的6个基本协议的一种.两个TCP意思非相同. ).TCP是一种可靠的面向连接的传送服务.它在传送数据时是分段进行的,主机交换数据必须建立一个会话.它用比特流通信,即数据被作为无结构的字节流. 通过每个TCP传输的字段指定顺

  • 详情解析TCP与UDP传输协议

    目录 一.什么是 socket ? 二.Socket 编程的重要概念 ① IP 地址 ② TCP/IP 端口 ③ 协议 三.socket 编程的 API 接口 ① Linux 下的 socket API 接口 ② windows 下的 socket API 接口 ③ TCP.UDP 通信的 socket 编程流程图 四.socket 的应用实例 ① 基于 TCP 的本地客户端.服务端信息交互实例 ② 基于 UDP 的本地客户端.服务端信息交互实例 一.什么是 socket ? Socket 的英

  • Java后端学习精华之TCP通信传输协议详解

    目录 Socket连接模型 消息协议 传输过程中数据类型需要了解的细节 TCP通信代码 上篇教程回顾 ServerSocket --监听客户端的连接,他的作用主要是建立一个连接 -ServerSocket -建立连接,拿到一个Socket -Telnet 127.0.0.1 8888- 客户端使用Telnet访问服务端 建立连接 -服务端可以拿到一个Socket的对象 -获取这个对象的输入输出流 -写入和读取数据 Socket连接模型 服务端和客户端通过Socket进行连接,虽然是一个Socke

  • TCP第三次握手传数据过程图解

    RFC793文档里带有SYN标志的过程包是不可以携带数据的,也就是说三次握手的前两次是不可以携带数据的(逻辑上看,连接还没建立,携带数据好像也有点说不过去).重点就是第三次握手可不可以携带数据. 先说结论:TCP协议建立连接的三次握手过程中的第三次握手允许携带数据. 对照着上边的TCP状态变化图的连接建立部分,我们看下RFC793文档的说法.RFC793文档给出的说法如下(省略不重要的部分): 重点是这句 "Data or controls which were queued for trans

随机推荐