tcp总结
一. 协议
TCP协议头部20个字节,注意TCP协议没有源地址和目的地址,那两部分信息在IP数据报中
1. 前4字节,源端口,目的端口,所以TCP可用的端口号范围是0-2^16-1(65535)
2. 4个字节序号,4个字节确认号。数据发送和接收的时候使用。
序号和确认号在发送方的作用。
序号的意义,首先序号标示了唯一的包,类似于一个ID,其次序号标示了发发送的顺序,因为TCP是要求发送和接收顺序必须一致的
确认号的意义,表示再确认号之前的数据都收到了
3. 4位数据偏移
TCP头部的长度是可变的,数据偏移是指,从TCP的头部到数据的开始位置的长度大小。但是注意这个长度大小的单位不是字节,而是32位比特位,也就是4个字节。
所以这个字段每增加10进制的1,TCP的头部就多32bits也就是4个字节,所以TCP的头部最大长度是15*4个字节,也就是60个字节。一般都是0101,也就是5*32/8 =
20字节
RFC的原文是这么说的:
Data Offset: 4 bits The number of 32 bit words in the TCP Header. This indicates where the data begins. The TCP header including options is an integral number of 32 bits long.
4. 6位0
5. 6位标志位:URG,ACK,PSH,RST,SYN,FIN
最常见的SYN,创建时候用。ACK收数据确认的时候用。FIN关闭连接的时候用。
PSH,连接以后发送数据时候的标识
URG,紧急,紧急插入一个数据包
RST,表明链接有问题,需要重新建连接
6. 2个字节窗口
接收方让发送方设置的窗口大小,控制发送方的发送速度
7. 2个字节校验和
校验首部和数据部分
8. 2个字节紧急指针
URG=1的时候,紧急数据的字节数
二. TCP建立连接
1. 首先客户端SYN标记为设置为1,发送序号为一个随机数,假设为N,确认号是0。
2. 服务器端收到以后,将ACK和SYN标志位同时设置为1,发送序号也是一个随机数,假设为M,确认号是N+1
3. 客户端接收到来自服务器的确认以后,设置ACK标记为1,发送序号为N,确认号为M+1
到此为止,两端都互相确认了对方的发送序号,客户端序号从N开始,服务端序号从M开始。双方都是对等的,没有什么服务端和客户端之分,任何一方都可以收发信息。
这是讲的最多的正常情况,假如,服务端没有第二次ACK会发生什么?
其实这种情况就是SYN攻击,操作系统中net.ipv4.tcp_max_syn_backlog配置了响应客户端发起SYN的队列最大长度,当这个队列被占满了就没法接收链接,攻击者自然达到攻击的目的。
当服务端收不到最后一次ACK的时候,会认为自己发送的SYN,ACK没发送成功,所以会隔一段时间重新发送SYN,ACK包,这个重试次数也是可以配置的net.ipv4.tcp_synack_retries,默认大概是180S左
右,这个选项还有一个对应的,就是对于客户端发送SYN没收到服务端的SYN,ACK时候的重试次数net.ipv4.tcp_syn_retries。
为了解决SYN攻击,操作系统还有一个配置是net.ipv4.tcp_syncookies,设置了这个的作用就是之前服务端生成初始的序号是随机的,现在改成通过来自于客户端SYN包的信息,做一个签名作为序号发
送给客户端,当客户端发送最后一次ACK的时候校验一次。但是这样做如果攻击者直接跳过第一二步,直接发送第三次的ACK也是个问题。
还有一点,当服务端没受到最后一次ACK对方就开始给自己发消息,或者多次发送SYN,ACK还是没收到客户端的ACK,服务端最后都会发送一个包,设置RST=1,然后关闭连接。
三.TCP可靠传输
1. 发送序号,和确认机制
继续刚才的例子,建立连接以后,客户端序号为N,确认号位M+1,服务端序号为M,确认号位N+1,因为现在他们处于对等的状态,所以谁先发送数据都一样的。
假设客户端先发送数据,客户端应该设置PSH和ACK都是1,继续发送确认号位M+1,但是这时候序号变成了N+1,假设发送的数据长度为X,这里开始我没明白服务端怎
么知道数据到底多长的,实际上,数据的长度不是在TCP协议中描述的,而是在IPV4的数据报协议中包含了数据长度。
收方,收到数据以后会将ACK标志设置为1,并发送确认号位N+1+X,因为服务端没有发送数据,所以服务端的序号是不变的。
那么下面如果服务端也发送点数据的情况,服务端也要设置PSH, ACK为1代表要发数据,同时设置发送序号为M+1,假设发送Y长度的数据,需要客户端发送确认号为
M+1+Y的ACK包
对于收方,假如确认号是N,含义就是我收到了第N-1字节的数据,但是要注意,比如发放发送三个包,收方收到第一个和第三个,那么第三个包的ACK不会发送。
2. 流量控制
滑动窗口,TCP发送数据可以用PIPELINE的方式,发方一次发送多个包,收方确认一个包,发方就又可以多发一个包,流量控制主要是让发送方发送数据不要太快,接收方可以通过设置参数来控制发送方的发送速率,设置窗口大小就在TCP协议的头部,有两个字节。那么收方如何调节这个窗口的策略就有一些讲究了,比如初始是多少,如何扩大或者缩小。
同时,连接的双方有可能既是发送方又是接收方,所以,他们各自维护一个发送窗口,和一个接收窗口。
3. 拥塞控制
拥塞控制是基于全局问题的考虑,当TCP发生重传的时候有可能会更加增加网络的负担。所以发送数据的时候除了取决于发送窗口以外,还增加了一个拥塞窗口,也就是发送的速率取这两个小的那个,这个值没有体现在协议的头部,而是由操作系统自己计算的。
慢启动,初始拥塞窗口是10, 每当收到一个ACK拥塞窗口增加1,每当过了一个RTT,增加一倍。
拥塞避免,当拥塞窗口增加到阈值以后就不能再按照倍增的方式,为了避免增长过快,每当收到一个ACK的时候,增长1/拥塞窗口,一个RTT增加1
当收不到收方的ACK的时候,发方能判断网络发生拥塞的方法有两种,一个是等待ACK的确认超时,那么拥塞窗口减少一半,还有可能收到
关于为什么会有三个重复的ACK?当收方收到乱序的数据包的时候会发送,比如3个包,收到了1,3丢了2,那么会ACK1那个包的ACK,这样发方就会从2开始重传,这个策略叫做快重传。同时还会降低拥塞避免时候的阈值,进入快恢复算法。
快恢复,在这个算法期间,重传重复ACK指定的数据包,拥塞窗口的增长,收到3个重复ACK增加1,如果收到新的ACK,说明网络恢复,就恢复拥塞窗口阈值,继续应用拥塞避免算法
四. TCP关闭
1. 关闭过程
主动关闭的一方设置FIN,ACK标记为1,序号为X的话,被动关闭一方回复ACK包,并且确认号位X+1。被动关闭的一方再发送FIN,ACK标记为1,序号为Y的话,主动关闭的一方再回复ACK包,确认号为Y+1,到此双方完成关闭流程。