就像上图一样,123处于1状态,456处于2状态,789处于3状态,10以后的处于4状态。而窗口就是指哪个框起来的。这里为6。
随着发送段被逐一的确认,这个窗口会往右滑动。
就像一个水池,总体积V,进水速度是s1,出水速度s2。当水池满了就不能再注入了,强行注入会溢出丢失。窗口就是那个水池。
滑动窗口实现面向流的可靠性:
1)最基本的传输可靠性来源于确认重传机制
2)滑动窗口的可靠性也是建立在确认重传机制上的
3)发送窗口只有收到目的端口对本段发送窗口内字节的ACK确认,才会移动发送串口的左边界。
4)接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有段未收到确认,但是收到了后面段的情况下,窗口不会移动,也不对后续段进行确认。以此确保发送端会对这个数据重传。
5、关于包头中确认号ack的理解
确认序号:仅当ACK标志为1时有效。确认号表示期望收到的下一个字节的序号
这里是拿三次握手之后,开始传输数据了进行分析。
服务器向客户端发送一个数据包后,客户端收到了这个数据包,会向服务器发送一个确认数据包。
传输数据的简要过程如下:
1)发送数据:服务器向客户端发送一个带有数据的数据包。该数据包中的序列号和确认号与建立连接第三步的数据包找那个的序列号和确认号相同。
2)确认收到:客户端收到该数据包,向服务器发送一个确认数据包。该数据包中,序列号是为上一个数据包中的确认号值。
而确认号为服务器发送的上一个数据包中的序列号+该数据包中所带数据的大小。
回复确认收到的ack = 收到了序列号 + 数据的大小(同时也表示下一次期望收到的序号)
这里我们直接拿Wireshark抓包进行分析:
实例1:客户端给服务器发送了”xcychongyong” 共13个字节。
先看,服务器收到的,也就是客户端发送的:seq是10,数据长度是13.
再来看服务器发送给客户端的确认包:根据上面的说明。ack应该是10 + 13 = 23
实例2:
如下图,208(就是192.168.0.208)一共向182(就是192.168.0.182)发送了6组数据。
过滤条件:tcp and (ip.src==192.168.0.182 or ip.dst==192.168.0.182)
对于182来说:
第一次回应时ack是4,结果208下一次发送的序号就是4。
第二次回应时ack是10,结果208下一次发送的序号就是10。
第三次回应时ack是19,结果208下一次发送的序号就是19。
以此类推…
再来分析一个互相发送的:
如图,一共发送了5次:
第一次182发给208,发的长度是7,seq是1.所以208回复的ack是8。也相当于告诉182:“182,你下次发的时候,序号就从8开始”。看第2个红框,seq就是8.
第二次208发给182,发的长度是11,seq是1,所以182回复的ack是12。也相当于告诉208:“208,你下次发的时候,序号就从12开始”。看第2个绿框,seq就是12.
同理,
182再发送一次给208,seq应该是17
208再发送一次给182,seq应该是33
ack表示期望下次接收到的序号。
那么ack是如何算出来的呢,就是通过收到的序号,和数据长度相加得来。
假设A收到B过来的数据(seq = 5,len = 15)。len表示数据长度。
那么A就会回复B,“刚才的数据我已经收到了,你接下来就发序号为20的包给我吧”。这样就保证了数据不会乱序。
综上,确认号就是下一次将要收到包的序号。同时也等于发送方的序号+数据长度(确认号在ACK标志位有效时才有用。)