第一次握手: Client将SYN置1,随机产生一个初始的序列号seq发送给Server,进入SYN_SENT状态
第二次握手: 收到SYN为1之后,知道客户端请求建立连接,将自己的SYN置为1,ACK置为1,产生一个acknowledge number = sequence number + 1,并随机产生一个自己的初始序列号,发送给客户端,进入SYN_RCVD状态
第三次握手: 客户端检查acknowledge number是否为序列号+1,ACK是否为1,检查正确之后将自己的ACK置为1,产生一个acknowledge number=服务器发的序列号+1,发送给服务器;进入ESTABLISHED状态;服务器检查ACK为1和acknowledge number为序列号+1之后,也进入ESTABLISHED状态;完成三次握手,连接建立。
本来的样子 :Client发出的第一个链接请求报文段并没有丢失,而是在某个网络结点长时间滞留了,以至于延误到丽娜姐释放后的某个时间到达server,但在他收到一脚的报文段后误以为C端又发了一个新的链接请求,于是向C端发出确认报文段,同意建立连接.
具体的过程 :假设不采取,只要S端确认,新的链接就建立了.由于C端并没有发出建立链接的请求,因此不会理睬S的确认,也不会向S端发送数据,但S端却以为新的运输链接已经建立,于是一直等待C端发来数据.S的很多数据就浪费掉了.
简单来说 :C不会向S的确认发出确认,S由于得不到确认,就认为C端没有要求建立连接.
可以.但是会降低传输的效率.第四次握手是指:
第二次握手:S端whiffsACK和acknowledge number,二S端的SYN和初始化序列在第三次时发送,原来协议中的第三次变成第四次握手. 出于优化目的,二三次可以合并
由于S端没接受到ACK确认,因此会重发之前的SYN+ACK(默认五次之后自动关闭连接)
C端收到后会重新传ACK给S端.
如果C端向服务器发送数据,服务器会以RST包响应.
服务器没收到一次客户端的请求后都会重新复位一个计时器,时间通常是2小时,弱之后还没有收到客户端的任何数据,服务器就会发送一个探测报文段,每隔75秒发送一个探测报文段,10个之后还是没有反应,就认为是故障了,关闭连接.
TCP连接的一方A,随机选择一个32位的序列号(Sequence Number)作为发送数据的初始序列号(Initial Sequence Number,ISN),比如为1000,以该序列号为原点,对要传送的数据进行编号:1001、1002…三次握手时,把这个初始序列号传送给另一方B,以便在传输数据时,B可以确认什么样的数据编号是合法的;同时在进行数据传输时,A还可以确认B收到的每一个字节,如果A收到了B的确认编号(acknowledge number)是2001,就说明编号为1001-2000的数据已经被B成功接受。
第一次挥手 C端将FIN置1,发送一个序列号seq给Server; 进入FIN_WAIT——1 状态
第二次挥手 收到之后发送一个ACK= 1,acknowledge number = 收到的序列号+1;进入CLOSE_WAIT状态。此时客户端已经没有要发送的数据了,但仍可以接受服务器发来的数据。次挥手
第三次挥手 Server将FIN置1,发送一个序列号给Client;进入LAST_ACK状态;
第四次挥手 C端收到服务器 FIN后,进入TIME_WAIT状态;接着将ACK置1,发送一个acknowledge number=序列号+1给服务器;服务器收到后,确认acknowledge number后,变为CLOSED状态,不再向客户端发送数据。客户端等待2*MSL(报文段最长寿命)时间后,也进入CLOSED状态。
因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复ACK,表示接收到了断开连接的请求。等到数据发完之后再发FIN,断开服务器到客户端的数据传送.(CLOSE_WAIT状态意义是什么?)
客户端没有收到ACK确认,会重新发送FIN请求
第四次挥手时,客户端发送给服务器的ACK有可能丢失,TIME_WAIT状态就是用来重发可能丢失的ACK报文。如果Server没有收到ACK,就会重发FIN,如果Client在2*MSL的时间内收到了FIN,就会重新发送ACK并再次等待2MSL,防止Server没有收到ACK而不断重发FIN。
MSL(Maximum Segment Lifetime),指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
使用滑动窗口协议实现流量控制。防止发送方发送速率太快,接收方缓存区不够导致溢出。接收方会维护一个接收窗口 receiver window(窗口大小单位是字节),接受窗口的大小是根据自己的资源情况动态调整的,在返回ACK时将接受窗口大小放在TCP报文中的窗口字段告知发送方。发送窗口的大小不能超过接受窗口的大小,只有当发送方发送并收到确认之后,才能将发送窗口右移。发送窗口的上限为接受窗口和拥塞窗口中的较小值。接受窗口表明了接收方的接收能力,拥塞窗口表明了网络的传送能力。
如果接收方没有能力接收数据,就会将接收窗口设置为0,这时发送方必须暂停发送数据,但是会启动一个持续计时器(persistence timer),到期后发送一个大小为1字节的探测数据包,以查看接收窗口状态。如果接收方能够接收数据,就会在返回的报文中更新接收窗口大小,恢复数据传送。
控制阻塞的四个算法:慢启动(Slow Start)、拥塞避免(Congestion voidance)、快重传 (Fast Retransmit)、快恢复(Fast Recovery)
慢启动:刚开始发送数据时,先把拥塞窗口(congestion window)设置为一个最大报文段MSS的数值,每收到一个新的确认报文之后,就把拥塞窗口加1个MSS。这样每经过一个传输轮次(或者说是每经过一个往返时间RTT),拥塞窗口的大小就会加倍
拥塞避免:当拥塞窗口的大小达到慢开始门限(slow start threshold)时,开始执行拥塞避免算法,拥塞窗口大小不再指数增加,而是线性增加,即每经过一个传输轮次只增加1MSS. 无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认),就要把慢开始门限ssthresh设置为出现拥塞时的发送方窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。(这是不使用快重传的情况)
快重传:快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
1快恢复:当发送方连续收到三个重复确认时,就把慢开始门限减半,然后执行拥塞避免算法。不执行慢开始算法的原因:因为如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方认为现在网络可能没有出现拥塞也有的快重传是把开始时的拥塞窗口cwnd值再增大一点,即等于 ssthresh + 3*MSS 。这样做的理由是:既然发送方收到三个重复的确认,就表明有三个分组已经离开了网络。这三个分组不再消耗网络的资源而是停留在接收方的缓存中。可见现在网络中减少了三个分组。因此可以适当把拥塞窗口扩大些。