Linux网编编程之 TCP协议 概述

TCP三次握手,四次挥手又来了

先谈谈TCP与UDP:

TCP是一个面向连接的、可靠的、基于字节流传输层协议。而UDP是一个面向无连接的传输层协议。
在这里插入图片描述

而用户数据报协议 UDP(User Datagram Protocol)是无连接的,尽最大可能交付,没有拥塞控制,面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信。
传输控制协议 TCP(Transmission Control Protocol)是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)。

具体分析TCP三大特性:
1.面向连接。所谓的连接,指的是客户端和服务器的连接,在双方相互通信之前,TCP需要三次握手建立连接,而UDP没有相应建立连接的过程。
⒉.可靠性。TCP花了很多的资源保证连接的可靠,这个可靠性体现在哪些方面呢?一个是有状态,另一个是可控制。
TCP 会精准记录数据收发,丢包情况,而且保证数据包按序到达,不允许半点差错。这是有状态。
当发生丢包的情况,TCP会根据具体情况调整自己的行为,控制自己的发送速度或者重发。这是可控制。对比UDP就是无状态,不可控的。
3.面向字节流。UDP的数据传输是基于数据报的,这是因为仅仅继承了IP层的特性,
而TCP为了维护状态,将一个个IP包变成了字节流

三次握手举例:A,B隔空交流:

A:我现在说话,你听得到不? —————> B ,证明了A有发送能力。
B:我听得到了,你那能听到吗 ? —————> A ,证明了A有发送能力,B有接收、发送能力。
A:好的,听见了 。 —————> B ,证明了A,B双方都存在接收、发送能力。
A,B从此隔空吐芬芳,开始了愉快的交流。

三次握手过程:/
从最开始双方都处于CLOSED状态。然后服务端开始监听某个端口,进入了LISTEN状态。
然后客户端主动发起连接,发送SYN,自己变成了STN-SENT状态。
服务端接收到,返回SYN和ACK(对应客户端发来的SYN),自己变成了SYN-REVD。
之后客户端再发送ACK给服务端,自己变成了ESTABLISHED状态;服务端收到ACK之后,也变成了ESTABLISHED状态。
三次握手的目的是确认双方发送和接收的能力。
TCP状态小知识:

CLOSED:没有使用这个套接字。
LISTEN:套接字正在监听连接。[调用listen后]
SYN_SENT:套接字正在试图主动建立连接。[发送SYN后还没有收到ACK]
SYN_RECEIVED:正在处于连接的初始同步状态。[收到对方的SYN,但还没收到自己发过去的SYN的ACK]
ESTABLISHED:连接已建立。

TCP标志位小知识:

ACK:用于确认收到数据,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。
SYN:用于建立一个连接,处于TCP连接建立过程。

下次发送对应的ACK序列号要加1,为什么呢?

SYN需要对端的确认,而ACK并不需要,因此SYN 消耗一个序列号而ACK不需要。
凡是需要对端确认的,一定消耗TCP报文的序列号。

四次握手可以不?

当然可以,更多次都可以。但为了解决现有问题,三次足矣。

四次挥手过程:

刚开始双方处于ESTABLISHED状态。
客户端请求断开,向服务器发送FIN报文,发送后客户端变成了FIN-WAIT-1状态。
注意,这时候客户端同时也变成了half-c1ose(半关闭)状态,即无法向服务端发送报文,只能接收。
服务端接收后向客户端确认,变成了CLOSED 一WAIT状态。
客户端接收到了服务端的确认,变成了FIN一WAIT2状态。
随后,服务端向客户端发送FIN,自己进入LAST -ACK状态,
客户端收到服务端发来的FIN后,自己变成了TIME一WAIT状态,然后发送ACK 给服务端。
注意了,这个时候,客户端需要等待足够长的时间,具体来说,是2个MSL(M axi murmSegment Lifetime,报文最大生存时间),在这段时间内如果客户端没有收到服务端的重发请求,那么表示ACK成功到达,挥手结束,否则客户端重发ACK。

TCP状态小知识二:

CLOSE_WAIT:远程套接字已经关闭,正在等待关闭这个套接字。[被动关闭的一方收到FIN]
FIN_WAIT_1:套接字已关闭,正在关闭连接。[发送FIN,没有收到ACK也没有收到FIN]
CLOSING:套接字已关闭,远程套接字正在关闭,暂时挂起关闭确认。[在FIN_WAIT_1状态下收到被动方的FIN]
LAST_ACK:远程套接字已关闭,正在等待本地套接字的关闭确认。[被动方在CLOSE_WAIT状态下发送FIN]
FIN_WAIT_2:套接字已关闭,正在等待远程套接字关闭。[在FIN_WAIT_1状态下收到发过去FIN对应的ACK]
TIME_WAIT:这个套接字已经关闭,正在等待远程套接字的关闭传送。
[FIN、ACK、FIN、ACK都完毕,这是主动方的最后一个状态,在过了2 MSL时间后变为CLOSED状态]

TCP标志小知识二:

FIN:终结连接标志,发送端已完成数据传输,请求释放连接,用来终结一个连接。

为什么是四次挥手而不是三次?

四次挥手的原因,客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。
因为服务端在接收到FIN,不会立即返回FIN,必须等到服务端所有的报文都发送完毕了,才能发FIN。因此先发一个ACK表示已经收到客户端的FIN,延迟一段时间才发FIN。这就造成了四次挥手。三次挥手的话等于说服务端将ACK和F IN的发送合并为一次挥手,这个时候长时间的延迟可能会导致客户端误以为FIN没有到达客户端,从而让客户端不断的重发FIN。

为什么等待2MSL?

MSL也称为"报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
TIME_WAIT:客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:
一、确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。假如客户端发动ACK后就立刻关闭,那么如果ACK丢失的话,服务端就会一直处于等待关闭确认的状态,超时后再发送关闭请求时,此时的客户端已经关闭,那么服务端就无法进行正常的关闭。

二、等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。

为什么是2MSL

我们知道服务端收到ACK,关闭连接。但是客户端无法知道ACK是否已经到达服务端,于是开始等待?等待什么呢?假如ACK没有到达服务端,服务端会为FIN这个消息超时重传,那如果客户端等待时间足够,又收到FIN消息,说明ACK没有到达服务端,于是再发送ACK,直到在足够的时间内没有收到FIN,说明ACK成功到达。这个等待时间至少是:服务端的响应时间 + FIN的传输时间,为了保证可靠,采用更加保守的等待时间2MSL。客户端发出ACK,等待ACK到达对方的超时时间MSL,等待FIN的超时重传,也是MSL,所以如果2MSL时间内没有收到FIN,说明了对方安全收到FIN。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程一时爽Cxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值