部分参考:https://blog.csdn.net/zhangdaisylove/article/details/47294315
源端口号:占2个字节,就是发起方的port
目的端口号:占两个字节,接收方的port
seq:占4个字节,发送方标记自己的segment的序列号,用以各个tcp报文的顺序。
ack:占4个字节,应答号,通常解释为期待接收到下一个序列号的报文,个人理解为这是第一个接收方未接收到的包
4位首部长度:占 4bit,表示tcp头部长度,单位为4个字节。
6位保留位
标志位:分别为URG、ACK、PSH、RST、SYN、FIN,
URG表示本包数据有紧急数据,ACK表示本包中ack值有效,PSH表示本包数据需要立即把本包数据从缓存区送出去,
RST表示连接有错误,重置连接,SYN表示建立连接,FIN表示结束连接。
16位窗口大小:表示接受方可以接受对方数据的缓存区大小。
16位校验和:
16位紧急指针:当URG被置位时,该值表示从开始到该值所指字节都是紧急数据。
一:滑动窗口
有时候接受方的缓存区已经满了,这个时候如果继续发送数据,那么接收方就会把数据丢弃掉,这样会白白浪费流量,所以在TCP的ACK中每次都会通知发送方自己可以接受的数据大小,也就是TCP报文中的16位窗口值,如果窗口变成了零以后,那么发送方就会停止发送,一直等到接收方可以接收数据,但是一直等待会出问题,如果其中ACK丢了,就会以为对方还不能接收数据,这个时候发送方可以发送窗口探测包。其中数据为0。
解释:当发送方收到接收方发来应答包后,应答号ack,加上报文中的窗口值减一,就是目前接受方的缓存最大可接受的数据包序列号,如下图ack=4,窗口值为6,那么4+6-1=9,也就是说发送知道目前最大可发送的数据包序号只能到9。
这就是滑动窗口,ack表示了窗口的左边界,ack+wind-1是窗口的右边界,即[ack,ack+win-1]区间,
目前只可以发送seq属于[ack,ack+win-1]区间的tcp数据包。由于ack一直变化,所以[ack,ack+win-1]属于向右滑动。
二:拥塞控制:
拥塞控制的目的避免网络拥塞,同时最大化网络利用率。不能一开始就发送大量数据到网络,以免造成网络拥塞,要对网络进行试探,并实时根据网络状态控制发送量,这就是拥塞控制的目的。这是一种试探网络状态的算法,判断当前网络最大可以一次性发送多少个MSS且不会导致网络拥塞。(MSS是TCP最大段大小,根据MTU计算,MTU为1500,则MTU-IP头-TCP头=1460)。
1. 如何实现:
拥塞控制的实现就是调整两个值:拥塞窗口值(cwnd),拥塞窗口阈值(ssthresh)。拥塞窗口阈值ssthresh是前一次拥塞时cwnd值的一半,建立连接之初,拥塞窗口cwnd=1,阈值ssthresh可以为无限大(因为不知道网络发送流量上限是多少,无法确定,设为一个较大值(ssthresh=65536),进行试探,或者指定其他适当值)。
2. 调整两个值的流程:
1)连接建立之初只发送一个数据包(cwnd=1),假定当前状态是最差,这样对网络负荷影响最小(避免拥塞)。
2)如果没有出现应答超时或者重复应答(网络没有拥塞,那么继续加大流量(最大化网络利用率,同时要避免拥塞)
- 此时当拥塞窗口在其阈值之下时(cwnd<ssthresh),继续翻倍增长窗口(cwnd=2*cwnd就是翻倍发送量)
- 如果在阈值之上(cwnd>=ssthresh),则线性增加窗口值(cwnd=cwnd+1)。
进入2);如果出现拥塞则进入3)。
3)出现应答超时或者重复应答(网络已拥塞,探测到拥塞值),如果
- 如果应答超时,将拥塞窗口阈值变为超时时的拥塞窗口的值的1/2(ssthresh=cwnd/2),将拥塞窗口值变为1(cwnd=1),并(网络状况很差,避免拥塞,立即将窗口设为0)
- 如果重复应答,将拥塞窗口阈值变为重复应答时拥塞窗口值的1/2(ssthresh=cwnd/2),然将拥塞窗口值变为阈值并加3(cwnd=ssthresh+3),然后。(网络状况有点差,但是没有很差,窗口缩半)
进入2)。
解释:这是发送方主机主动控制的值,是为发送方的TCP建立的一个受网络状况而定的窗口。每次发送数据时都会根据拥塞窗口和滑动窗口(对方ack应答包中的16位窗口大小)大小对比,选取值小的那一个作为数据包的长度值。
拥塞控制是最大化网络利用率,流量大小随网络状态动态调整。开始值要小但是要快速增加(指数增加),当到达阈值时流量增速要放缓(线性增加)以免很快又造成网络拥塞,另外由于第一次建立连接ssthresh的值较大,一般第一次 只会出现进翻倍发送。典型图如下所示:
总结:拥塞窗口阈值总是变为发生拥塞时的1/2(ssthresh=cwnd/2),拥塞窗口值在应答超时时变为0,在重复应答时变为当前值1/2后再加3(即新阈值加3)。
三、拥塞窗口和滑动窗口
拥塞窗口也可以决定出一个最大的发送序列号,滑动窗口也可以,需要二者取其小。另外拥塞窗口是发送方主动感知网络状态,进而决定的发送数据的流量,而滑动窗口是接收方告知发送方的。
四、其他
3:超时控制,窗口控制,流量控制,拥塞控制对比
1)超时控制,只是在每一个数据都要确定收到 ACK,没有收到ACK超过时间限定就会重发。
2)窗口控制,会对持续收到的同一个ACK三次以后重发数据,并且如果长时间没有收到ACK,那么也会重发数据。
3)流量控制,就是确认接收方是否有足够缓存接受数据,否则一个劲发会浪费网络流量。
4)拥塞控制,这个是试探网络是否可以接受目前的数据发送大小。
5)网络和主机缓存一起决定着数据发送数据的大小。
4:延迟应答
有时候没必要对每个数据都立刻发送ACK,可以稍微等待下一个数据也收到了,然后发送ACK,或者等待时间过长也发送ACK。
5:捎带应答:
就是把应答放在其他的数据包中一起发送过去。
6:半关闭:
TCP 的 shutdown() 可以停留在一个只接收数据,而不写数据的状态中,这个时候状态称为半关闭。