您的位置:首页 > 理论基础 > 计算机网络

TCP浅谈(上)

2015-10-01 13:15 302 查看
TCP是一个很复杂的协议,在学习计算机网络的时候对有些东西还是一知半解,写这篇文章主要有两个目的:

一:重新复习一下TCP协议,巩固一下自己所学的,特别是一些一知半解的东西。

二:也希望帮助一些网友了解一些这方面的基础知识,搞清楚之前一些似是而非的东西。

所以,本文只是一些关于TCP的基础的必不可少的知识,还请大家指教。

1.首先我们来回顾一下网络的OSI七层模型:(图片来源于 百度)






如上图所示,我们需要知道TCP在七层模型中的第四层--Transport层,IP在第三层--Network层,ARP在第二层--Data Link层,在第二层上的数据我们成为Frame,在第三层上的数据称为Packet,第四层上的数据称为Segment。我们要传输的数据依次传输到TCP的Segment中,然后TCP的Segment会传输到IP的Packet中,最后再传输到以太网的Frame中,传到对端后,各个层解析自己的协议,把数据交给更高层的协议处理。

有了这些基础之后我们再来看看TCP头格式。

TCP头格式:






TCP头格式(图片来自

从上图可以看出一下几点:

从头格式中可以看出TCP的包是没有IP地址的,因为那是IP 层上的事,但是有源端口和目标端口
Sequence Number 是包的序号,用来解决网络包乱序的问题。
Acknowledgement Number 就是ACK,用于确认收到,用来解决不丢包的问题。
Window 也就是著名的滑动窗口(Sliding Window),用于解决流控的。
TCP Flag,也就是包的类型,主要是用于操控TCP的状态机的,也就是表示如下意义: 
* F : FIN - 结束; 结束会话 
* S : SYN - 同步; 表示开始会话请求 
* R : RST - 复位;中断一个连接 
* P : PUSH - 推送; 数据包立即发送 
* A : ACK - 应答 
* U : URG - 紧急 
* E : ECE - 显式拥塞提醒回应 
* W : CWR - 拥塞窗口减少
TCP状态机:

其实,网络上的传输是没有连接的,包括TCP也是一样,而TCP所谓的“连接”,其实只不过是在通讯的双发维护一个“连接”状态,让它看上去好像是有连接一样,所以,TCP 的状态变换非常重要。

下面是“TCP协议的状态机”和“TCP建立连接”、“TCP断开连接”、“传数据”的对照图:





TCP状态机(来源

为什么建立连接要3次握手,而断开连接需要4次握手?

建立连接的3次握手:主要是要初始化Sequence Number 的初始值,通信的双方要互相通知对方自己的初始化的Sequence Number即Inital Sequence Number,也就是上图中的x和y,这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上的传输问题而成为乱序的就是说TCP会根据这个序号来拼接数据。
断开连接的4次挥手:其实仔细看是2次,因为TCP 是全双工的,所以,发送方和接收方都需要Fin和Ack。只不过,有一方是被动的,所以看上去就成了所谓的4次挥手。如果两边同时断开连接,那就会进入到CLOSING状态,然后到达TIME_WAIT 状态。
关于建立连接时的SYN超时:试想一下,如果server端接到了clien发的SYN后回了SYN-ACK后client掉线了,server端没有收到client发送回来的ACK,那么,这个连接处于一个中间状态,即没成功,也没失败。于是,server端会在一定时间内将客户端没有收到的SYN-ACK重发一定次数(在Linux下,默认重试次数为5次,重试的间隔时间从1s开始每次都翻售,5次的重试时间间隔为1s,
2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s,TCP才会把断开这个连接)。

TCP重传机制:

TCP要保证所有的数据包都可以到达,所以必需要有重传机制。

接收端给发送端的Ack 确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,3,于是回Ack 4,然后收到了5(注意此时4没有收到),遇到这种情况TCP该怎么继续传输数据呢?我们知道,SeqNum和Ack 是以字节数为单位,所以Ack确认的时候,不能跳着确认,只能确认最大的连续收到的包,不然,发送端就以为之前的都收到了。


超时重传机制


一种是不回ack,死等3,当发送方发现收不到3的ack超时后,会重传3。一旦接收方收到3后,会ack 回 4——意味着3和4都收到了。

但是,这种方式会有比较严重的问题,那就是因为要死等3,所以会导致4和5即便已经收到了,而发送方也完全不知道发生了什么事,因为没有收到Ack,所以,发送方可能会悲观地认为也丢了,所以有可能也会导致4和5的重传。

对此有两种选择:
一种是仅重传timeout的包。也就是第3份数据。
另一种是重传timeout后所有的数据,也就是第3,4,5这三份数据。

这两种方式有好也有不好。第一种会节省带宽,但是慢,第二种会快一点,但是会浪费带宽,也可能会有无用功。但总体来说都不好。因为都在等timeout,timeout可能会很长(在下篇会说TCP是怎么动态地计算出timeout的)

快速重传机制


于是,TCP引入了一种叫Fast Retransmit 的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不用等timeout了再重传。

比如:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。
Fast Retransmit只解决了一个问题,就是timeout的问题,它依然面临一个艰难的选择,就是重转之前的一个还是重装所有的问题。对于上面的示例来说,是重传#2呢还是重传#2,#3,#4,#5呢?因为发送端并不清楚这连续的3个ack(2)是谁传回来的?也许发送端发了20份数据,是#6,#10,#20传来的呢。这样,发送端很有可能要重传从2到20的这堆数据(这就是某些TCP的实际的实现)。可见,这是一把双刃剑。
好了,上篇就到这里,有不对的地方还请指教。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络