TCP协议(RFC793)
TCP报文格式
- 校验和相关见:UDP协议
TCP连接
连接建立(三次握手)
注:SYN报文段不能携带数据(因为连接还未建立),但会消耗一个序列号
- 客户端 -> 服务端:SYN=1,seq=x(x为一个随机值,会消耗一个序列号)
- 服务端 -> 客户端:SYN=1,ACK=1,ack=x+1,seq=y(此时服务端会为TCP连接分配资源)
- 客户端 -> 服务端:ACK=1,ack=y+1,seq=x+1(客户端为TCP连接分配资源,可以携带数据,若不携带数据则不消耗序列号,即下次发送数据时的序列号seq依然为x+1)
注:服务器端的资源是在第二次握手时分配的,而客户端的资源是在第三次握手时分配的,这就使得服务器易受SYN洪泛攻击
连接释放(四次挥手)
注:FIN报文段可以携带数据,但若不携带数据也会消耗一个序列号
- 双方均可以结束TCP连接,下述假设A先结束TCP连接,B为另一方
- A -> B:FIN=1,seq=u(即使不携带数据,也要消耗一个序列号,此时A不能发送数据,但B依然可以发送数据)
- B -> A:ACK=1,ack=u+1,seq=v(对A发出的释放报文确认,B继续发送数据)
- B -> A:FIN=1,ACK=1,ack=u+1,seq=w(B释放连接,继续确认A发送的报文)
- A -> B:ACK=1,ack=w+1,seq=u+1(对B的报文进行确认,B收到确认后释放资源,而A需要等待2*MSL最长报文段寿命后才能释放资源,防止该确认丢失,还可以避免此次连接的报文对下次连接有干扰)
可靠传输
- 序号:建立在字节流上,而不是报文段
- 确认:累计确认,确认已收到的字节至第一个丢失字节的序号
- 重传:超时重传 + 冗余ACK重传(接收方每收到一个失序的报文段,就向发送方发送一个ACK,而发送方收到3个对某个报文段的ACK,就重传该报文段)
流量控制
- 通过TCP报文中的确认号字段和窗口字段来进行流量控制,可接收字节序号不超过:确认号 + 窗口大小 - 1
拥塞控制
- 慢开始:cwnd初始为1个MSS(最大报文段,单位为字节),每收到一个对新报文段的确认,就将cwnd加1。即每经过1个RTT,cwnd *= 2。若此时cwnd >= ssthresh(慢开始门限),则cwnd = ssthrseh(cwnd不能直接越过ssthresh)
- 拥塞避免:cwnd >= ssthresh时,每经过一个RTT,cwnd就加1
- 网络拥塞的处理:当未按时收到确认(可以认为出现了拥塞),将ssthresh设置为当前cwnd的一半(但不能小于2),将cwnd重新设置为1,执行慢开始算法
- 快重传:当发送方连续收到3个重复的ACK时(此时网络还未拥塞,因为还能收到ACK),直接重传对方尚未收到的报文段
- 快恢复:当发送方连续收到3个重复的ACK时,将ssthresh设置为当前cwnd的一半(但不能小于2),然后将cwnd设置为ssthresh的值,执行拥塞避免