TCP首部
16位源端口 16位目的端口
32位序号
32位确认号
4位首部长度 保留6位 URG ACK PSH RST SYN FIN 16位窗口大小
16位校验和 16位紧急指针
选项
数据
TCP首部共计20字节
TCP校验和
TCP头中的校验和,需要在TCP头的前边加上一个含有源目IP的伪首部。
MSS段
MSS段表明最大报文长度,发送该值的一端将不接受超过这个长度的TCP报文段,这通常是为了避免IP分段。
2MSL
2MSL等待状态:TIME_WAIT状态。是任何丢弃的报文在网络上存活的最大时间。在2MSL期间内,定义这个连接的socket四元组不能再次被使用。
TCP服务器呼入连接请求队列
TCP服务器呼入连接请求队列,已经完成三次握手,但是还没有被应用层接收。如果对于新的连接,连接队列已经没有空间,TCP将不理会收到的SYN。也不发回任何报文,客户端将超时重传。
Nagle算法
Nagle算法是指一个TCP连接最多只能有一个未确认的的未完成小分组,该分组的确认到达之前不能发送其他的小分组。TCP_NODELAY选项可以关闭该算法。
TCP的滑动窗口
使用TCP的滑动窗口协议时,接收方不必确认每一个收到的分组,在TCP中,ACK是累积的,表示接收方已经正确收到了确认序号减1的所有字节。
TCP零窗口
窗口为0表示接收方已经收到了所有的数据,但是这些数据都在TP接收方的TCP缓冲区里,应用程序还没有读取。在应用程序读取后,会发送另一个不确认任何新数据的ACK,只用来增加窗口的右边沿,因此称为窗口更新。
滑动窗口
滑动窗口指的是窗口左边沿向右边靠近称为窗口合拢,这种现象发生在数据被发送和确认时。窗口右边沿向右边移动时将允许发送发送更多数据,称为窗口张开,这种现象发生在另一端的接收进程读取已经确认的数据并释放了TCP的接收缓存。
慢启动:
原因:发送方和接收方之间存在多个路由器和速率较慢的链路,一些中间路由器必须缓存分组,有可能耗尽路由器的内存。所以需要慢启动。
算法通过分析新分组进入网络的速率应该与另外一端返回确认的速率相同而进行工作。
具体实现为发送方TCP增加一个窗口,拥塞窗口(congestion window),记为cwnd。当建立TCP连接的时候,拥塞窗口初始化为1,每收到一个ACK,拥塞窗口加1。拥塞窗口是发送方使用的流量控制,而通告窗口则是接收方使用的流量控制。
带宽时延乘积
带宽时延乘积: capacity=bandwith * round-trip time(s)
TCP定时器
TCP有4个定时器:
- 重传定时器
- 坚持定时器
- 保活定时器
- 2MSL定时器
RTT
TCP超时重传最重要的一部分就是对给定连接的往返时间测量(RTT)。TCP跟踪该参数并相应的改变超时时间。
M :测量到的RTT
R: RTT估计器
R = xR+(1-x)M 其中的x为一个0.9的平滑因子
RTO:重传超时时间 = yR y为推荐值为2的时延离散因子
使用基于均值和方差计算RTO,将比使用均值常数倍计算RTO提供更好的相应。
Err:是刚刚测量结果与当前RTT估计器之差。
A:被平滑的RTT
D:被平滑的均值偏差
Err = M - A
A = A + g*Err
D = D + h(|Err|-D)
RTO=A + 4D
当一个超时和重传发生时,当重传数据确认最后到达时,不能更新RTT估计器。因为无法确定ACK对应那一次传输。
报文丢失的TCP现象
发送端:TCP对收到的重复ACK进行计数,当收到第三个时,就假定一个报文已经丢失并重传那个序号的一个报文。
接收端:接收端接收一个失序的报文,TCP将保存该数据,并返回一个已成功接收数据最大序号+1的ack给发送端。
拥塞避免算法
拥塞避免算法是一种处理丢失分组的方法。丢失分组意味着源主机和目的主机之间的某处网络发生了拥塞。
拥塞避免算法和慢启动算法是两个目的不同的算法,单在实际中这两个算法放在一起实现,对每个链接维护两个变量:cwnd(拥塞窗口)和慢启动门限(ssthresh)
当拥塞发生时(超时或者收到重复确认),ssthresh设置为当前cwnd的一半。如果是超时引起了拥塞,则cwnd设置为1。
拥塞算法是每收到一个确认将cwnd增加1/cwnd。
if cwnd <= ssthres{
慢启动(指数级增加)
}else{
拥塞避免(加性增加)
}
快速重传和快速恢复算法:
TCP收到一个失序的报文段时,TCP立即产生一个重复ACK,这个ACK不应该被延迟,该ACK目的在于让对方知道收到一个失序的报文段,并告诉对方自己期待的序号。
TCP发送方不知道一个重复的ACK是由于丢失报文引起的还是由于几个报文重新排序导致的,因此需要等待少量重复ACK到来。一般如果是重新排序,只可能产生1-2个重复ACK,如果收到3个或者以上重复ACK,就非常可能是一个报文段丢失。于是我们就重传丢失报文,不需要等待超时定时器溢出。在这种情况下没有执行慢启动,原因是收到重复的ACK不仅仅是告诉我们丢失了一个分组,由于接收方只有在收到另外一个报文段的时候才产生重复的ACK,也就是说接收端和发送端之间有数据流动,我们不想执行慢启动突然减少数据流。
TCP坚持定时器
设置该定时器原因是因为TCP不对ack包文进行确认,TCP只确认有数据的ACK报文。如果发送方接收到接收方的0窗口通知,后边丢失了TCP的打开窗口ACK,会引起发送端无法发送数据问题。为防止这种情况,发送方使用一个坚持定时器周期性的向接收方查询,以便发现窗口是否已经增大。
窗口探查包含一字节的数据。TCP总是允许发送已经关闭窗口1字节的数据。
与超时定时器不同,TCP从不放弃发送窗口探查。
糊涂窗口综合症
糊涂窗口综合症是指当发送端应用进程产生数据很慢、或接收端应用进程处理接收缓冲区数据很慢,或二者兼而有之;就会使应用进程间传送的报文段很小,特别是有效载荷很小; 极端情况下,有效载荷可能只有1个字节;传输开销有40字节(20字节的IP头+20字节的TCP头) 这种现象。
TCP保活定时器
保活定时器主要为了服务器端设计,用来检测半开放连接。实现方式是如果一个连接在两个小时内没有任何数据传输,则服务器向客户发送一个探查报文。如果有数据则两个小时的计时复位。如果探查的客户端已经重启,则服务端会接收到一个RST。如果对端无响应,75秒后超时,连续发送10个,没有响应则认为客户端已经关闭并终止连接。
探查的方式是发送一个比将要发送序号小1的报文,引起对端响应该报文,该报文告诉探查端正确的序号。
TCP收发数据优化
首包优化
将initCwnd默认值调大 2–>10
建连优化
减少syn和syn ack的重传时间
窗口大小修改
中间设备可以修改window的大小,可以中间限速。
平滑发包
利用RTT将数据发送打散,有效规避瞬间拥塞。如下图所示:
CDN加速
(1)下层和上层是长连接,省去三次握手的时间
(2)cwnd可以很大减少RTT次数
丢包预判
根据历史数据预判
RTO探测
减小RTO的值
带宽评估
增大发包速度,传输速度是否减少
带宽争抢
多个发送端,增加发送数据量,丢包随机丢失,所以传输的数据量增大。
链路质量记忆
链路质量记忆,记录一些有效的参数。
检测运营商光纤有问题
1、目的Ip和端口一致
2、随机改变源端口
3、由于五元组hash到不同链路,发现运营商链路问题。
网络干扰方法
握手干扰
http 302干扰
DNS劫持
判断是否被劫持
1、RTT过短,比如去美国,很短的RTT
2、ttl大幅度跳变 linux默认的ttl是64
3、正确的数据扔可达
4、诱饵找到干扰的机器