TCP运输连接管理
一条完整的运输连接分为三个阶段:连接建立,数据传送,连接释放。类比现实生活中的一次完整的电话通信:先打通,再唠嗑,最后挂断。细分该过程,连接建立需要解决以下问题:
1.连接双方都必须确认对方存在(打电话必须确认电话开机,信号良好 不能是空号)
2.要允许双方协商一些参数(最大报文段长度,最大窗口大小,服务质量等)
3.能够对运输实体资源进行分配(缓存大小 最大连接个数)
选择序号 seq=x,其中SYN=1表示客户端请求连接,seq=x表示该客户端开始接收数据的序列号是x。也就说服务器发送的数据的第一个字节放在x处
第二次握手:如果服务器同意连接,则发送SYN=1(同步连接),确认号ACK=1 确认收到了客户端的请求,同意确认连接;并且发送ack=x+1 确认收到了客户端发送的起始序列号x在此同时发送随机值seq=y 告诉客户端,服务器的下一个报文起始位置的值
第三次握手:客户端收到服务器同意连接的报文段,发送ACK=1,确认客户端收到了服务器的报文段,并且发送ack=y+1确认收到了服务器的起始序列号y,由于该报文段虽然不携带数据,但是也需占有一个序列号,所以客户端的起始序列号变为seq=x+1
断开连接需要四次挥手:
第一次挥手:客户端发送FIN=1,并且告诉服务器下一个报文的起始序列号是seq=u
第二次挥手:服务器发送ACK=1表示收到了上一条报文段 并且发送小写的ack=u+1
告诉客户端收到了起始序列号u 并且发送自己的下一个报文的起始序列号seq=w
第三次挥手:服务器数据发送完毕,ACK和FIN同时为1,并且告诉客户端此时自己下一个报文段的起始序列号seq=w,再次确认收到了客户端的起始序列号ack=u+1
第四次挥手:客户端接受到服务器的FIN=1,发送ACK=1,确认接收到了上次的报文段
由于该条报文段虽然不包含数据,但是也会占用一个序列号,所以起始序列号变为
u+1 并且发送ack=w+1 表示收到了服务器的起始序列号w
注意:在四次挥手过程中的几个小细节:
1:原理上第二次挥手是可以省略的,但是往往当服务器收到客户端的关闭请求的同时还在发送数据,先发送ACK表示收到了关闭请求,但是暂时还不 能关闭,直到服务器发送完所有数据,才会令FIN=1 表示同意关闭连接
2:第四次挥手后,客户端会进入TIME_WAIT状态等待2MSL(2倍的网络片段最大存活时间)而不是立即关闭,因为最后一次ACK可能丢失,Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT 状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。(关于这个问题后续再做讨论)
3:三握手的意义,为了防止网络延迟造成的服务器资源浪费,假如客户端发送了连接请求,但是在某个网络节点上滞留了,很久很久以后服务器才收到客户端的连接请求,同意建立连接,并且等待客户端确认并且发送数据,而此时客户端早已不需要此次连接,将不会理睬server端的确认,这样将会白白浪费server端的资源。
一条完整的运输连接分为三个阶段:连接建立,数据传送,连接释放。类比现实生活中的一次完整的电话通信:先打通,再唠嗑,最后挂断。细分该过程,连接建立需要解决以下问题:
1.连接双方都必须确认对方存在(打电话必须确认电话开机,信号良好 不能是空号)
2.要允许双方协商一些参数(最大报文段长度,最大窗口大小,服务质量等)
3.能够对运输实体资源进行分配(缓存大小 最大连接个数)
TCP建立连接采用CS方式 连接建立需要三次握手:(准备工作,服务器被动打开)
第一次握手:客户端主动打开,并且发送同步请求报文段,该报文段内容包括SYN=1选择序号 seq=x,其中SYN=1表示客户端请求连接,seq=x表示该客户端开始接收数据的序列号是x。也就说服务器发送的数据的第一个字节放在x处
第二次握手:如果服务器同意连接,则发送SYN=1(同步连接),确认号ACK=1 确认收到了客户端的请求,同意确认连接;并且发送ack=x+1 确认收到了客户端发送的起始序列号x在此同时发送随机值seq=y 告诉客户端,服务器的下一个报文起始位置的值
第三次握手:客户端收到服务器同意连接的报文段,发送ACK=1,确认客户端收到了服务器的报文段,并且发送ack=y+1确认收到了服务器的起始序列号y,由于该报文段虽然不携带数据,但是也需占有一个序列号,所以客户端的起始序列号变为seq=x+1
断开连接需要四次挥手:
第一次挥手:客户端发送FIN=1,并且告诉服务器下一个报文的起始序列号是seq=u
第二次挥手:服务器发送ACK=1表示收到了上一条报文段 并且发送小写的ack=u+1
告诉客户端收到了起始序列号u 并且发送自己的下一个报文的起始序列号seq=w
第三次挥手:服务器数据发送完毕,ACK和FIN同时为1,并且告诉客户端此时自己下一个报文段的起始序列号seq=w,再次确认收到了客户端的起始序列号ack=u+1
第四次挥手:客户端接受到服务器的FIN=1,发送ACK=1,确认接收到了上次的报文段
由于该条报文段虽然不包含数据,但是也会占用一个序列号,所以起始序列号变为
u+1 并且发送ack=w+1 表示收到了服务器的起始序列号w
注意:在四次挥手过程中的几个小细节:
1:原理上第二次挥手是可以省略的,但是往往当服务器收到客户端的关闭请求的同时还在发送数据,先发送ACK表示收到了关闭请求,但是暂时还不 能关闭,直到服务器发送完所有数据,才会令FIN=1 表示同意关闭连接
2:第四次挥手后,客户端会进入TIME_WAIT状态等待2MSL(2倍的网络片段最大存活时间)而不是立即关闭,因为最后一次ACK可能丢失,Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT 状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。(关于这个问题后续再做讨论)
3:三握手的意义,为了防止网络延迟造成的服务器资源浪费,假如客户端发送了连接请求,但是在某个网络节点上滞留了,很久很久以后服务器才收到客户端的连接请求,同意建立连接,并且等待客户端确认并且发送数据,而此时客户端早已不需要此次连接,将不会理睬server端的确认,这样将会白白浪费server端的资源。