TCPIP协议机制详解
确认应答(ACK)机制(保障TCP稳定的核⼼机制) 爬楼购物车
每⼀个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下⼀次你从哪⾥开始发
确认应答可能带来的问题:
1.发送的数据根本就没有传送到达主机2,因此主机2就不会回传⼀个确认应答的报⽂。
2.ACK丢失了
当我们的主机1给主机2发送了数据之后,经过⼀端时间主机1并没有收到主机2的应答的情况也是有的,所以这个时候为了确保数据的准确到达,TCP就有了超时重传机制
超时重传机制
主机1没有收到主机2的确认应答有以下两种情况:
1.发送的数据根本就没有传送到达主机2,因此主机2就不会回传⼀个确认应答的报⽂。
主机1发送数据给2之后, 可能因为⽹络拥堵等原因, 数据⽆法到达主机2;
如果主机1在⼀个特定时间间隔内没有收到2发来的确认应答, 就会进⾏重发;
2、,主机A未收到B发来的确认应答,可能是主机2收到了数据也回传了确认应答报⽂ ,但因为ACK丢失了
因此主机B会收到很多重复数据. 那么TCP协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉
这时候我们可以利⽤前⾯提到的序列号, 就可以很容易做到去重的效果
如图:主机2收到了主机1发来的数据,但是发给主机1的确认应答并没有准时到达主机1,所以主机1也会因为没有收到确认应答⽽再次重新将数据发送过去。但实际情况却是我们的主机2第⼀次就已经收到了主机1的数据。但是主机1依旧会重发数据已确保主机2已经收到数据,从⽽进⾏下⼀次的数据转发。可想⽽知主机2就会收到很多的重复数据,但是重复的数据显然是不需要的,那么TCP协议就
需要能够识别那些重复的数据并且要将冲符的数据丢弃掉,这个时候序列号就发挥他的⼀项作⽤了——去重。每⼀个数据都有⾃⼰的序列号,如果主机2收到重复的数据那么必然机会产⽣多个序列号相同的数据,那么序列号相同的数据就必然是重复的数据。
门禁监控我们提到⼀个特定的时间间隔,这个时间⼜是如何规定的?
TCP为了保证⽆论在任何环境下都能⽐较⾼性能的通信, 因此会动态计算这个最⼤超时时间
※连接管理机制
在正常情况下, TCP要经过三次握⼿建⽴连接, 四次挥⼿断开连接
led防水灯串
举个例⼦:证明双⽅均有接收和发送的能⼒
羟乙基纤维素钠两次握⼿⾏不⾏?多次呢?
不⾏哦,三次握⼿的成功率很⾼,不需要更多次握⼿。多次握⼿还会浪费资源。
压力检测器
记住其中的重要状态
接下来有确认应答,超时重传等
此处下去详看KJ,记住重要状态
三次握⼿:
(1)服务器程序先运⾏起来后,当调⽤listen设置监听套接字之后,进⼊LISTEN状态。然后调⽤accept阻塞等待来⾃客户端的连接请求; (2)客户端再运⾏,分配⽂件描述符之后,调⽤connect向服务器发起连接请求,阻塞等待服务器的应答。发出带有SYN同步标志位的同步报⽂段,此时进⼊SYN_SENT状态;
(3)服务器收到客户端的SYN同步报⽂段后,将该连接放⼊内核等待队列中,并进⼊SYN_RECV状态。此时,服务器向客户端发出带有ACK标志位的确认报⽂段,确认收到连接请求,并等待客户端连接建⽴之后的确认信号;
(4)客户端收到服务器的ACK确认报⽂段之后,认为服务器同意建⽴连接,此时客户端进⼈ESTABLISH状态,并建⽴连接(将连接描述组织起来),然后向客户端发出连接已经建⽴的确认信号;
(5)服务器收到确认信号之后,知道客户端已经建⽴连接,此时服务器也进⼊ESTABLISH状态建⽴连接;并分配新的⽂件描述符connfd 与客户端进⾏数据通信;
此时,三次握⼿后,双⽅的连接建⽴成功。开始进⾏数据通信:
(6)然后服务器调⽤read阻塞等待来⾃客户端的数据请求;
(7)客户端调⽤write向服务器发出数据请求;
(8)服务器收到数据请求之后,从read返回,向客户端发出带有ACK的确认数据报,确认收到请求,然后对客户端的数据进⾏处理;
(9)客户端收到服务器的确认信号后,调⽤read阻塞等待服务器的数据响应信号;
(10)服务器处理完客户端的数据之后,向客户端发出响应数据报;
(11)客户端收到服务器的响应数据报之后,从read返回,并向服务器发出收到响应的确认信号;
(12)服务器收到确认信号之后,继续调⽤read阻塞等待来⾃客户端的数据请求;此时,循环(6)~(11);
四次挥⼿:
举个例⼦:假如⼥⽣有东西要收拾
阀门手轮
问题:三次挥⼿可以吗?
有可能可以。 对应到程序当中:接收缓冲区没有数据了,那么就可以直接关闭连接。
过程:
四次挥⼿断开连接:
(13)某⼀时刻,客户端不再发出数据请求,⽽是调⽤close关闭连接。并向服务器发出带有FIN标志位的结束报⽂段,此时,客户端进⼊FIN_WAIT_1状态,等待服务器的确认信号;
(14)服务器收到客户端的FIN结束报⽂段,知道客户端要关闭连接了,此时服务器进⼊CLOSE_WAIT状态,进⾏关闭连接前的⼀些后序操作,并向客户端发出带有ACK的确认报⽂段,表明他知道客户端要关闭连接了;
(15)客户端收到服务器的确认报⽂段之后进⼊FIN_TIME_2状态,等待服务器处理完后续操作和服务器的结束报⽂段;
(16)服务器处理完后续操作之后,调⽤close关闭连接,进⼊LAST_ACK状态,并向客户端发出关闭连接的FIN结束报⽂段,然后等待客户端的最后⼀个ACK确认报⽂段;
(17)客户端收到服务器端的结束报⽂段之后,向服务器发出ACK确认报⽂段,此时,进⼊TIMA_WAIT状态。
(18)服务器收到确认报⽂段之后,进⼊CLOSED状态彻底断开连接。
(19)客户端在TIME_WAIT之后等待⼀个2MSL后,进⼊CLOSED状态,彻底断开连接。
TIME_WAIT:
想⼀想, 为什么是TIME_WAIT的时间是2MSL?
AN:MSL是TCP报⽂的最⼤⽣存时间, 因此TIME_WAIT持续存在2MSL的话就能保证在两个传输⽅向上的尚未被接收或迟到的报⽂段都已经消失(否则服务器⽴刻重启,可能会收到来⾃上⼀个进程的迟到的数据, 但是这种数据很可能是错误的);同时也是在理论上保证最后⼀个报⽂可靠到达(假设最后⼀个ACK丢失, 那么服务器会再重发⼀个FIN. 这时虽然客户端的进程不在了, 但是TCP连接还在, 仍然可以重发
LAST_ACK);
CLOSE_WAIT
⼀般⽽⾔,对于服务器上出现⼤量的 CLOSE_WAIT 状态, 原因就是服务器没有正确的关闭 socket, 导致四次挥⼿没有正确完成. 这是⼀个BUG. 只需要加上对应的 close 即可解决问题.