TCP传输控制协议 读书笔记

来源:互联网 发布:php开源博客系统 编辑:程序博客网 时间:2024/05/21 18:15

TCP提供一种面向连接的、可靠的字节流服务。


TCP报文



首部中的6个标志比特

URG 紧急指针(urgent pointer)有效

ACK 确认序号有序

PSH 接收方应该尽快将这个报文段交给应用层

RST 重建连接

SYN 同步序号用来发起一个连接

FIN 发端完成发送任务



TCP连接建立——三次握手

1)客户发送一个SYN段指明打算连接的服务器的端口,以及初始序号(客户端ISN);

2)服务器发回包含服务器初始序号(服务器端ISN)的SYN报文段作为应答,同时,将确认序号设置为客户的ISN加1以对客户的SYN报文段进行确认;(一个ISN将占用一个序号)

3)客户必须将确认序号设置为服务器的ISN加1以对服务器的SYN报文段进行确认。



TCP连接终止——4次握手

1)客户端关闭连接时,会向服务器发送一个FIN,用来关闭从客户到服务器的数据传送;

2)服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1,一个FIN也占用一个序号,同时服务器向应用程序传送一个文件结束符;

3)服务器程序收到文件结束符后,就关闭它的连接,向客户发送一个FIN;

4)客户收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。


建立一个连接需要三次握手,而终止一个连接经过4次握手,这由TCP的半关闭造成的,TCP连接是全双工的,因此每个方向必须单独关闭。


收到一个FIN只意味着在这一方向上没有数据流动,TCP在接收到一个FIN后仍能发送数据。


当建立一个连接时,每一方都有用于通告它期望接收的MSS选项(只能出现在SYN报文段中),如果一方不接受来自另一方的MSS值,则MSS就定位默认值536字节(加20字节IP首部和20字节TCP首部以适合756字节IP数据报)。


TCP所有可能的状态变迁:



TCP正常建立连接和终止所对应的状态:



对一个具体实现所给定的MSL值(报文段最大生存值),处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL,这样可以让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)


并发服务器处于忙时,TCP如何处理呼入的连接请求:(伯克利TCP实现)

1)正等待连接请求的一端有一个固定长度的连接队列,该队列中的连接已被TCP接受(即三次握手已经完成),但还没有被应用层所接受;

2)应用层将指明该队列的最大长度,这个值通常称为积压值(backlog),它的取值范围是0~5之间的整数,包括0和5;

3)当一个连接请求(即SYN)到达时,TCP使用一个算法,根据当前队列中的连接数来确定是否接收这个连接。

积压值说明的是TCP监听的端点已被TCP接受而等待应用层接受的最大连接数,与系统所允许的最大连接数(BSD 积压值乘以3除以2加1)和并发服务器所能并发处理的最大客户数无关。

4)如果对于新的连接请求,TCP监听的端点的连接队列中还有空间,TCP模块将对SYN进行确认并完成连接的建立。但应用层只有在三次握手中的第三个报文段收到后才知道这个新连接,如果服务器应用层还不知道这个新连接,但客户进程已经发出数据,服务器的TCP仅将接收的数据放入缓冲队列;

5)如果对于新的连接请求,连接队列已经没有空间,TCP将不会受理收到的SYN,也不会发回任何报文段(RST),如果应用程序不能及时接受已被TCP接受的连接,这些连接可能占满整个连接队列,客户的主动打开最终超时。


Nagle算法

微小 分组(tinygram):数据部分很少(可能只有一个字节的数据)

要求 :一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组的确认到达之前不能发送其他的小分组,相反,TCP收集这些少量的小分组,并在确认到来时以一个分组的形式发送出去。

优势:它是自适应的,确认到达得越快,数据也发送得越快。


另一种形式的流量控制方法

TCP滑动窗口协议:该协议允许发送方在停止并等待确认前可以连续发送多个分组。


慢启动 :慢启动为发送方增加了一个窗口——拥塞窗口,当与另一个网络的主机建立TCP连接时,拥塞窗口被初始化为1个报文段(即对端通告的段大小),每收到一个ACK,拥塞窗口就增加一个报文段,发送方取拥塞窗口和通过窗口中的最小值作为发送上限。

注:拥塞窗口是发送方使用的流量控制,而通告窗口则是接收方使用的流量控制。


通道容量:capacity(bit) = bandwidth(b/s) * round-trip time(s)


紧急方式(urgent mode):它使一端可以告诉另一端有些具有某种方式的“紧急数据”已经放置在普通的数据流中。

紧急指针,标准协议是指向紧急数据的最后一个字节,但伯克利实现多为指向紧急数据最后一个字节的下一个字节。


TCP超时与重传

往返时间(RTT)测量:TCP必须测量在发送一个带有特别序号的字节和接收到包含该字节的确认之间的RTT(因为数据报文段和ACK之间通常没有一一对应的关系,这意味着测量到的是一个估计值)。

TCP规范使用低通过滤器更新被平滑的RTT估计器 R<-aR+(1-a)M  (R为上一次的估计值,a是一个推荐值为0.9的平滑因子,M表示所测量到的RTT)

对应的重传超时时间RTO(Retransmission TimeOut): RTO = Rb (b是一个推荐值为2的时延离散因子)

不足:在RTT变化范围很大时无法跟上这种变化,会引起不必要的重传


往返时间变化起伏很大时,基于均值和方差来计算RTO,将比作为均值的常数倍数来计算,RTO能提供更好的响应

均值偏差是对标准偏差的一种好的逼近,但却更好计算,新的估算公式

Err = M - A (A是被平滑的RTT,M是测量值,Err是刚得到的测量结果与当前的RTT估计器之差)

A<-A + g*Err (增量g起平均作用,取值0.125)

D<-D + h*(|Err| - D) (偏差的增益是h,取值是0.25)

RTO = A + 4D 

优点:当RTT变化时,较大的偏差增益将使RTO快速上升,g,h和倍数4均是2的乘方,这样一来均可通过移位操作实现


Karn算法(解决重传多义性问题)

当一个超时和重传发生时,在重传数据的确认最后到达前,不能更新RTT估计器,因为我们并不知道ACK对应哪次传输,并且,由于数据被重传,RTO已经得到了一个指数退避,我们在下次传输时使用这个退避后的RTO,对于一个没有被重传的报文段而言,除非收到了一个确认,否则不要计算新的RTO。


拥塞避免算法(处理丢失分组)

该算法假定由于分组受到损坏引起的丢失是非常少的(远小于1%),因此分组丢失就意味着在源主机和目的主机之间的某处网络上发生了拥塞,分组丢失的两种指示:发生超时和接收到重复的确认。


拥塞避免算法和慢启动算法需要对每个连接维持两个变量:一个拥塞窗口cwnd和一个慢启动门限ssthresh。工作过程如下:

1)对一个给定的连接,初始化cwnd为1个报文段,ssthresh为65535个字节;

2)TCP输出例程的输出不能超过cwnd和接收方通告窗口的大小;

3)当拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小的一半(cwnd和接收方通告窗口大小的最小值,但最少为2个报文段),此外,如果是超时引起了拥塞,则cwnd被设置为1个报文段(这就是慢启动);

4)当新的数据被对方确认时,就增加cwnd,但增加的方法依赖于我们是否正在进行慢启动或拥塞避免,如果cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。慢启动一直持续到我们回到拥塞发生时所处位置的一半才停止(因为我们记录了在步骤2中给我们制造麻烦的窗口大小的一半),然后执行拥塞避免。

慢启动算法初始设置cwnd为1个报文段,此后每收到一个确认就加1,会使窗口按指数方式增长,发送1个报文段,然后是2个,接着是4个……

拥塞避免算法要求每次收到一个确认时将cwnd增加1/cwnd,与慢启动的指数增加比起来,这是一种加性增长(additive increase),我们希望在一个往返时间内最多为cwnd增加1个报文段(不管在这个RTT中收到了多少个ACK),


快速重传和快速恢复算法

修改之前:认识到收到一个失序的报文段,TCP立即产生一个ACK(一个重复ACK),该重复ACK不应该被迟延,该重复的ACK目的在于让对方知道收到一个失序的报文段,并告诉对方自己希望收到的序号。

我们不知道一个重复的ACK是由一个丢失的报文段引起的,还是由于仅仅出现了几个报文段的重新排序,因此我们等待少量重复的ACK到来,假如这只是一些报文段的重新排序,则在重新排序的报文段被处理并产生一个新的ACK之前,只可能产生1~2个重复的ACK,如果一连串收到3个或3个以上的重复ACK,就非常可能是一个报文段丢失了。于是我们就重传丢失的数据报文段,而无需等待超时定时器溢出,这就是快读重传算法。接下来执行的不是慢启动算法而是拥塞避免算法,这就是快速恢复算法。


算法实现过程:

1)当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半,重传丢失的报文段,设置cwnd为ssthresh加上3倍的报文段大小;

2)每次收到另一个重复的ACK时,cwnd增加1个报文段大小并发送一个分组(如果新的cwnd允许发送);

3)当下一个确认数据的ACK到达时,设置cwnd为ssthresh(第一步中设置的值),这个ACK应该是在进行重传后的一个往返时间段内对步骤1中的确认, 另外,这个ACk也应该是对丢失的分组和收到的第1个重复的ACK之间所有中间报文的确认,这一步采用的是拥塞避免,因为当分组丢失时我们将当前的速率减半。


常见的ICMP差错:源站抑制,主机不可达和网络不可达

基于伯克利实现对应的处理

*一个接收到的源站抑制引起拥塞窗口cwnd设置为1个报文段大小来发起慢启动,但是慢启动门限ssthresh没有变化,所以窗口将打开直至它或者开放了所有的通路(受窗口大小和往返时间的限制)或者发生了拥塞。

*一个接收到主机不可达或者网络不可达实际上都被忽略,因为这两个差错都被认为是短暂现象。

0 0
原创粉丝点击