tcp三次握手建立连接和4次挥手断开连接

我们知道tcp协议是有连接、可靠、面向字节流传输。接下来将会介绍具体建立连接过程和断开连接,即三次握手和四次挥手字

在这里插入图片描述
主动请求连接的一方会最后发送ACK,主动断开连接的一方会最后发送ACK。
服务端状态改变:

  1. [CLOSED -> LISTEN] 服务器端调用listen后进入LISTEN状态, 等待客户端连接;
  2. [LISTEN -> SYN_RCVD] ⼀旦监听到连接请求(同步报文段), 就将该连接放入内核等待队列中, 并向 客户端发送SYN确认报文.
  3. [SYN_RCVD -> ESTABLISHED] 服务端⼀旦收到客户端的确认报文, 就进入ESTABLISHED状态, 可以进行发送接收数据了.
  4. [ESTABLISHED -> CLOSE_WAIT] 当客户端主动关闭连接(调用close), 服务器会收到结束报文段, 服务器返回确认报文段并进入CLOSE_WAIT;
  5. [CLOSE_WAIT -> LAST_ACK] 进入CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的 数据); 当服务器真正调用close关闭连接时, 会向客户端发送FIN, 此时服务器进入LAST_ACK状态, 等待最后⼀个ACK到来(这个ACK是客户端确认收到了FIN)
  6. [LAST_ACK -> CLOSED] 服务器收到了对FIN的ACK, 彻底关闭连接.
    客户端状态改变:
    1.[CLOSED -> SYN_SENT] 客户端调用connect, 发送同步报文段;
    2.[SYN_SENT -> ESTABLISHED] connect调用成功, 则进入ESTABLISHED状态, 开始接收发送数据;
    3.[ESTABLISHED -> FIN_WAIT_1] 客户端主动调用close时, 向服务器发送结束报文段, 同时进入 FIN_WAIT_1;
    4.[FIN_WAIT_1 -> FIN_WAIT_2] 客户端收到服务器对结束报文段的确认, 则进入FIN_WAIT_2, 开始 等待服务器的结束报文段;
    5.[FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报文段, 进⼊入TIME_WAIT, 并发出 LAST_ACK;1
    6.[TIME_WAIT -> CLOSED] 客户端要等待一个2MSL(Max Segment Life, 报文最大生存时间)的时间, 才会进入CLOSED状态.
    接下来看几个问题:
    1.为什么主动方要等待或者TIME_WAIT状态有什么用?并且为什么是2个MSL时间?
    如果启动server端,然后启动client,然后用ctrl+c使程序server终止,紧接着再运行server,结果如下:
    在这里插入图片描述
    为什么会出现这种错误呢?
    是因为虽然server程序终止,但是tcp协议的连接并没有断开,那么就不会再监听同样的server端口。
    TCP协议规定,主动关闭连接的一方要处于TIME_WAIT状态,等待2个MSL(MSL是最大报文生存周期)的时间才能回到CLOSED状态;由于server是主动关闭一方,那么在TIME_WAIT期间就不能再次监听同样的端口;
    为什么会有TIME_WAIT?
    可靠的终止TCP连接,若处于time_wait的client发送给server确认报文段(ack)丢失的话,serve 等待一段时间后,没有收到ack会认为fin包没有发送过去,会重新再次发送fin包到主动方。如果client发送ack直接关闭,如果同样的端口再次建立连接,就会有新的socket,那么刚被动方发送的fin包就有可能对这个新的连接造成影响,这是不希望看到的,所以主动方发送最后一个ack后需要等待一段时间,那么等待多久合适,这里需要是2个MSL时间:
    1.确保ack发送成功,
    2.假设ack没有发送成功,被动方再次发送fin包,这个fin包在网络中最大生存周期是MSL,过了MSL,这个fin包就算没有发送到主动方,会被丢弃在网络中,那么如果同样的端口再次建立连接,这个重新发送的fin包将不会造成影响(因为被丢弃),如果fin包发送成功,主动方接受到fin包在剩余时间内回复ack。
    TIME_WAIT为了保护主动关闭方。
    为什么TIME_WAIT是 2MSL?
    1. time_wait持续的时间是2MSL,保证旧的数据能够丢弃。由于网络中的数据最大存在MSL。保证旧的数据丢弃的好处是:保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失,否则服务器重启后可能会收到来自上一个进程的迟到的数据,但这种数据很有可能就是错误的。
    2.同时也保证最后一个报文可靠到达,假设最后一个ACK丢失,那么服务器会重新发送一个FIN包,这时虽然客户端的进程不在了,但是TCP连接依然在,会重发最后一个ACK。
    为什么建立连接是3次握手,断开连接是4次挥手?
    这是由于TCP的半关闭造成的。因为TCP连接是全双工的(即数据可在两个方向上同时传递)。所以进行关闭时每个方向上都要单独进行关闭。这个单方向的关闭就叫半关闭。当一方完成它的数据发送任务,就发送一个FIN来向另一方通告将要终止这个方向的连接。发送了FIN只是表示这端不能继续发送数据(应用层不能再调用send发送),但是还可以接收数据。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据,比如:如主机A收到主机B的FIN断开TCP连接请求,只是表示主机B已经发送完数据,主机A收到FIN后作出应答,并终止这个方向的数据传输,此时处于半关闭状态。但是主机A仍然可以发送数据的,只有当主机A发送完数据并发送FIN给主机B时,主机B才停止这个方向的数据传输,并关闭TCP连接。

为什么三次握手最后一次要回复ack ?

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

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

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

在这里插入图片描述
两次握手:服务器回复ACK和SYN,服务器以为连接建立成功,会消耗资源维护这个连接,但是这个回复可能由于一些原因丢失,即连接并没有建立成功,那么就消耗了服务器资源。
三次握手:即使第三次ack回复失败,也只是客户端认为将连接建立成功,异常在客户端。
如果是四次握手:服务器回复ack,ack丢失,异常在服务器,同二次握手。
2)在很多时候,TCP连接的断开都会由TCP层自动进行,例如当ctrl+c终止你的程序,TCP连接依然会正常关闭。
当第三次握手失败服务器并不会重传ack报文,而是直接发送RTS报文段,进入CLOSED状态。这样做的目的是为了防止SYN洪泛攻击
泛洪攻击
SYN泛洪攻击则是客户端向服务器发送SYN报文之后就不再响应服务器回应的报文。由于服务器在处理TCP请求时,会在协议栈留一块缓冲区来存储握手的过程,当然如果超过一定的时间内没有接收到客户端的报文,本次连接在协议栈中存储的数据将会被丢弃。攻击者如果利用这段时间发送大量的连接请求,全部挂起在半连接状态。这样将不断消耗服务器资源,直到拒绝服务。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值