TCP
TCP
TCP是面对流的协议,提供可靠的面向连接的运输服务,是点对点通信。(下载等应用场景)
UDP是面向报文的协议,不提供可靠交付,并且不需要连接,不仅仅支持点对点而且支持多播和广播。(群视频聊天、语音等)
TCP首部(头格式)
TCP请求的格式入下图所示
并不是所有的内容都很重要,标了颜色的比较重要。
- 序列号:在建立连接时由计算机生成成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送⼀次数据,就累加⼀次该序列号的大小。用来解决TCP请求的乱序问题。
- 确认应答号:指下⼀次希望收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决丢包的问题
- 控制位:
- ACK:该位为 1 时,确认应答的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。
- RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
- SYN:该位为 1 时,表示希望建立连接,并在其序列号的字段进行序列号初始值的设定。
- FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位为 1 的 TCP 段。
为什么TCP可靠
TCP有三次握手建立连接和4次挥手关闭连接的机制,还有滑动窗口和阻塞控制算法。最关键的是还有超时重传机制。对于每份报文进行校验,保证报文的可靠性。
超时重传
当发送端的TCP发送数据时,会给数据编号。且每发送一次数据就会等待接收端返回ACK(表示收到了)。当没收到ACK时,发送端就会重新发送数据。如果接收端收到了数据,并发送了ACK但是因为网络或其他原因导致发送端没收到ACK时。接收端就会重复收到发送端发出的数据,但是因为发送端对每个数据都进行了编号,所以接收端重复收到数据时,直接丢弃就行了。当发送端重新发送几次数据但还是接受不到ACK时,发送端就会当方面断开连接。
滑动窗口
发送端的TCP一次次发送数据等待返回ACK效率就会很低。因此正常情况下发送端会将数据一部分,一部分的发送。这个就是滑动窗口技术。
假定总共有6份数据要发送,窗口大小为3。那么发送端一次发送就会把1~3的数据全部发送给接收端。当接收到接收端返回的1号数据的ACK后就会将窗口滑到2-4,如果没接收到2号数据的ACK那么此时就会重发2-4数据。发送窗口的大小时根据接收端的接受能力来调整的。接收端会将窗口大小放在TCP首部返回给发送端。
阻塞控制
网络带宽是有限的,因此在网络拥挤时发送端还发送大量数据就有可能导致网络瘫痪。接收端没有接收到数据,发送端接收不到ACk进行重传又加重网络瘫痪。
这个时候就需要阻塞控制,阻塞窗口的大小由网络环境决定。
一开始阻塞窗口较小,之后每接收到一次ACK就表示当前网络时畅通的。就会增加阻塞窗口的大小,发送数据时的窗口大小取阻塞窗口和接收端返回的窗口大小的最小值。随着阻塞窗口的变大,网络压力变大导致ACK接受失败时,,就会减小阻塞窗口。
TCP的三次握手
在说明握手前我们首先得直到TCP报文中有很多标识,在握手中用到的有SYN(同步)、ACK(确认),设置为1就是开启,设置为0就是关闭。报文中还携带有随机生成的序号Sequence和确认号AckSequence
第一次握手
假定Sequence为10086,客户端将SYN设置为1(表示想和服务器同步),并把报文发送给服务端。
第二次握手
服务器接收到报文后,根据端口号等信息运算生成一个序号Sequence假定为10000和一个确认序号AckSequence**,AckSequence的值是Sequence+1也就是10087。并将SYN和ACK设置为1,表示确认同步,发送给客户端。
第三次握手
客户端接收到服务器的报文后,将ACK设置为1,并生成Sequence和AckSequence,这个Sequence为第二次握手的AckSequence+1,也就是10001。AckSequence为上一次的Sequence+1,也就是10088。然后将报文发送给服务端。
三次握手过后客户端和服务端就建立了连接可以发送HTTP请求了。
Sequence和AckSequence
总的来说就是第一次生成的Sequence为随机生成,第二次生成的Sequence为服务器根据端口号等信息运算生成的,第三次的Sequence是上一次的AckSequence+1。
AckSequence都是上一次Sequence+1
为什么要三次握手,两次行不行
不行,
- TCP连接稳定的关键就是一对序列号Sequence,只有两次握手只能确定客户端的Sequence,无法确定服务端的Sequence。就有可能出现客户端接收到的数据包重复或者顺序混乱的问题。
- 会导致重复连接。在网络环境比较复杂的情况,客户端可能会连续发送多次请求。如果只设计成两次握手的情况,服务端只能一直接收请求,然后返回请求信息,也不知道客户端是否请求成功。这些过期请求的话就会造成网络连接的混乱。
TCP的4次挥手
挥手的发起者可以是客户端,也可以是服务端。下面以客户端发起为例。在挥手中用到的标识有FIN,ACK
第一次挥手
客户端向服务端发送FIN=1,Sequence=u(意思是我没有数据要给你啦)。
第二次挥手
服务端向客户端返回ACK=1,Sequence=a,AckSequence=u+1(意思是,我接收到你的第一次挥手了)。但是服务端还有可能有未发送完毕的数据。
第三次挥手
服务端将未发送完毕的数据全部发送完毕后,向客户端发送FIN=1,Sequence=b,AckSequence=u+1(意思是,我数据发送完成啦可以关闭连接了)
第四次挥手
客户端向服务端返回ACK=1,Sequence=u+1,AckSequence=b+1(表示收到了,我要准备关闭了)。此时客户端不会立刻关闭连接,而是会等待2MSL,防止因为网络问题ACK丢失。如果期间没有收到回复(表示服务器正常关闭)就会关闭连接,不然就会进行重传。
为什么建立连接只要三次握手,而关闭连接需要四次挥手
因为在主机A请求关闭连接时,主机B可能还有数据没有发送完。所以主机B会在第二次挥手时先返回ACK表示自己接收到了关闭请求,然后再发送完剩余的数据后进行第三次挥手返回FIN表示数据已经全部发送完了,可以关闭连接了。
第四次挥手等等2MSL才关闭连接
防止因为网络问题第四次挥手的ACK丢失。等待2MSL时用来重发可能丢失的ACK的。