day 7:重传机制;TCP三次握手(详细描述);TCP四次握手

重传机制

重传机制有两种:go-back-N,selective repeat。stop and wait协议下的重传机制比较简单,因此重点讨论sliding window下的重传机制。

go-back-N:顾名思义,假如N=4,我一开始发的是data1、2、3、4,结果1、3、4都有ack了,2直到timeout了都还没有ack。于是,原本的节奏是准备发5、6、7、8,现在我只能重发2、3、4、5。

selective repeat:也是顾名思义,假如N=4,我一开始发的是data1、2、3、4,结果1、3、4都有ack了,2直到timeout了都还没有ack。于是,原本的节奏是准备发5、6、7、8,但这时候我不干全部重发这么笨的事情,我默认“如果N个包里面丢了一个,那就是只有那个包丢了,其他包都安然无恙地到达了”,我只重发丢了的那个包。因此,我接下来就发2、5、6、7。

这两种机制的使用取决于接收方的sliding window的尺寸N,如果接收方N=1,使用的是go-back-N,因为只有1个缓存空间,在收到data2之间,接收方不会确认收到3;接收方N=N(大于1),则使用的是selective repeat,因为有多个缓存空间。使用两种重传机制遵循的核心思想是:接收方的sliding window不要收到重复的包,以免给网络带来额外的负担。

TCP三次握手

结合前几个day的内容进行一次总结:
1.active端给passive端发送一个SYN包
——其TCP头设置了syn,填写了(随机)序列号SA

syn对应在TCP头中的flag部分设置为0x002

为什么要随机序列号?——day 4:TCP功能,头,连接,三次握手(简要描述),UDP

2.passive端收到该SYN包以后,回复一个(ACK+SYN)包
——其TCP头设置了syn和ack,填写了(随机)序列号SP确认序列号SA+1

注意:passive端只发了一个包,里面同时设置了ack和syn,对应在TCP头中的flag部分设置为0x012

3.active端收到passive端的SYN包以后,回复一个ACK包
——其TCP头设置了ack,填写了序列号SA+1确认序列号SP+1

ack对应在TCP头中的flag部分设置为0x010

该ACK包数据长度为0字节,因此该ACK包之后的第一个数据包序列号仍然是SA+1

除此之外,还有另外一种特殊但常用的建立连接的方法——网络地址转换NAT:对等的应用程序同时发送给对方SYN,然后同时回复给对方ACK+SYN,这个时候算作是四次握手。

0.到底为什么要发SYN和发ACK这么麻烦?
最主要原因:为了防止旧的重复的【连接启动】引起混乱
详细解释:

TCP协议对反复使用的特定连接没有任何限制。 由此产生的问题是-“ TCP如何从连接的先前版本中识别重复的段?” 如果快速连续地打开和关闭连接,或者由于内存丢失而断开连接然后重新建立连接,此问题将变得很明显。
1.设计中的基本概念是,通过TCP连接发送的每个八位字节的数据都有一个序列号。 由于每个八位位组都已排序,因此可以确认每个八位位组。 所采用的确认机制是累积性的,因此序列号X的确认ACK表示已接收到所有但不包括X的八位位组
2.当创建新的连接时,将使用一个初始序列号(ISN)生成器来选择一个新的32位ISN。 生成器绑定到(可能是虚拟的)32位时钟,该时钟的低阶位大约每4微秒递增一次。 因此,ISN大约每4.55小时循环一次。 因为我们假设网段中的网段停留时间不超过最大网段寿命(MSL),并且MSL小于4.55小时,所以我们可以合理地假设ISN是唯一的
3.由于序列号不与网络中的全局时钟相关,并且TCP可能具有不同的机制来选择ISN,因此需要三向握手。 第一个SYN的接收者无法知道该段是否是旧的延迟段,除非它记得连接上使用的最后一个序列号(这并不总是可能的),因此它必须要求发送者进行验证 这个SYN


以TCP状态机为例,说明为什么要ACK,如何解决重复的初始化SYN:
正常状态下的三次握手:
在这里插入图片描述
注意图中的4.和5.的包内容。5.描述了含有数据时的TCP传输,就是不停地在传输ACK包,包含当前数据包的序列号SA、对方上一次发过来的数据包的最后一个字节对应的序列号SB+1作为确认序列号。
例如:
A–>B:<SEQ=1><ACK=1><LEN=474>;
B–>A:<SEQ=1><ACK=475><LEN=1448>;
B–>A:<SEQ=1449><ACK=475><LEN=1448>;
异常状态下的握手:注意异常步骤3之后B和A的动作在这里插入图片描述

1.为什么连接的时候不是两次握手,即省去最后一次A回复ACK?
——标准答案是会形成“死锁”。通俗地讲就是:就因为A不发ack,导致B不知道A是否同意建立B对A的连接,于是B就不停地重发syn,等待A回复个ack。然而由于A对B的连接已经建立完成了,所以A就兴高采烈地往B发data,等待B回复ack。这个死锁就是:
A:你不给我发ack,我就不停向你重发data,直到你发data的ack为止。
B:你不给我发ack,我就不停向你发syn,直到你发syn的ack为止”
2.那为什么不是四次呢?
——三次就能搞定的事情,为什么还一定要发四次呢?如果能合并,为什么还要多发一次浪费时间呢?
3.那为什么NAT要发四次呢?
——
4.为什么断开时是四次握手呢?
——你自己事情做完了想下班去恰饭,别人事情还没做完不想去恰饭,你不能勉强别人跟着自己断开去恰饭对吧
5.为什么第三次握手还要再发一次SEQ,但是passive端收到ACK以后不用再发送一个SEQ?
——
6.会不会存在一方想建立连接,另一方不想建立连接的情况?
——
7.如果没有收到对方的ACK怎么办?
——那就timeout以后,辛苦自己再发一次SYN咯

结束时,需要四次握手
但是注意,在收到FIN、回复了ACK以后,并不能立马拆掉连接:万一你发的ACK半路丢了、对面实际上没收到,那该怎么办?解决方法就是:回复了ACK以后,等待2×MSL(Maximum Segment Lifetime)的时间,如果时间到了,没有再收到FIN,那就默认对方收到了ACK,自己就可以着手拆除连接了。
不过,一旦数目多起来,问题就变得麻烦起来了。一旦处于等待状态的socket多了,对于服务器本身来说,会使得服务器变慢。解决方法是:可以直接rst然后delete端口,或者设置等待时间为0。操作系统不会重新启动服务器,而是直接重用端口号

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值