网络原理-传输层补充1
TCP协议
连接管理
正常情况下,TCP通过三次握手建立链接,四次挥手断开链接.
三次握手
握手流程:客户端向为服务端发送SYN同步报文段请求建立链接,服务端在收到SYN同步报文段后,会返回给客户端一个ACK确认报文段和SYN同步报文段,这两个报文段可以和二为一,表现为ACK和SYN二合一的报文段,客户端在接收到这个报文段后返回给客户端一个ACK报文段.在三次握手流程完毕后,服务端才会真的存储客户端的信息.流程简图:
为什么要进行三次握手?
1.确保通信路径流畅.
2.确保通信双方都具有发送和接收能力.
在客户端发送SYN报文,服务端接收到后,服务端就知晓服务端接收能力正常,客户端发送能力正常,随后服务端返回ACK+SYN报文,客户端接收到后,客户端就知晓客户端发送,接收能力正常,服务端发送,接收能力正常,随后客户端返回给服务端ACK报文,服务端接收到后就知晓服务端发送能力正常,客户端接收能力正常.
3.在握手的同时也会协商一些参数.例如:TCP通信的序号起始量,这个起始量是有一些算法决定的,确保就算和同一个客户端再次通信,通信的序号仍与上次不同.
四次挥手
挥手一般由客户端主动发出,服务端也可主动进行挥手.挥手流程:客户端发送FIN结束报文段,服务端收到后返回ACK确认报文段和FIN结束报文段,客户端收到后返回ACK确认报文段.注意:这里服务端返回的ACK和FIN不能合并成一个报文段,因为在应用层调用socket.close()后才会在传输层发送FIN结束报文段,在收到结束报文段后,应用层可能还有其他的一些逻辑需要执行,不能第一时间发送FIN结束报文段.
断开链接是为了删除对端的数据结构.四次挥手并不是唯一的断开链接方式,当发生异常时会有其他方法断开链接.
TCP的部分状态
LISTENING:服务器启动,ServerSocket对象创建完毕,开始监听链接.
ESTABLISHED:三次握手完成,链接建立完毕.
CLOSE_WAIT:等待代码调用socket.close来主动发起FIN,收到对端FIN之后会进入这个状态.
TIME_WAIT:本端给对方发起FIN后,对端也发给我FIN后,本端会进入TIME_WAIT,给最后一个ACK的重传留有时间.
客户端在收到服务端的FIN报文后进入TIME_WAIT状态并返回一个ACK报文段,如果客户端重传了FIN报文段说明ACK报文段丢失,则客户端重传ACK报文段,如果客户端等到TIME_WAIT状态超时,依旧没有收到服务端重传的FIN报文段,说明ACK报文段正常传达,服务端已关闭链接,那么客户端也就关闭链接.
滑动窗口
如前面所讲,为了保证可靠性,TCP会发送消息然后等待ACK之后,才会发送下一个消息.这样的情况性能较差,尤其是数据往返的时间较⻓的时候.如果一次发送多条数据,这样就能大大提高发送的效率.滑动窗口就算维护这个一次发送多条数据而产生的机制,是一种补救措施.
1.窗口大小指的是⽆需等待确认应答⽽可以继续发送数据的最⼤值.
2.前窗口大小个段不需要等待ACK,直接发送.
3.收到ACK后,窗口向后滑动,继续发送后续报文段.
4.操作系统内核为了维护这个滑动窗⼝,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉.
5.窗口越大,网络的吞吐率越大.
滑动窗口示意图:
图中一次性发送三个报文段,在接收到相应的ACK之后进行下一个报文段的发送.
如果在滑动窗口时,发生了丢包会怎么样?
ACK丢包
如图,ACK3001丢包,但是发送方收到了ACK4001,就知晓4001之前的接收方都已收到,接下来从4001开始发送即可,这种情况无需重传.
数据丢包
在数据发送丢包后,发送端会一直收到1001这样的ACK报文,像是在说"我想要的是1001"一样.
如果发送端连续收到了三次重复的ACK报文,则认为对应的数据报文丢包,进行重传.
接收方在接收到重传后的数据后,会返回已经接收到的数据正确的ACK,如图中的6001.