TCP/IP是互联网的核心协议,也是大多数网络应用的核心协议。就前面一段时间面试中问到的TCP/IP问题,这里给出一个简单的小结。 TCP由RFC793、RFC1122、RFC1323、RFC2001、RFC2018以及RFC2581定义。 (1) TCP概述a. TCP提供的是面向连接的全双工服务。TCP所有的数据会匹配到由源地址,目的地址,源端口,目的端口构成的一个TCP连接之上。TCP连接是一种需要建立的资源,可以通过之后会讲到的握手机制来完成。UDP是一种基于尽力而为机制的协议,不存在UDP连接资源的建立,资源的处理往往由应用层协议代劳了。 b. TCP是提供的可靠服务。TCP有确认机制来保证数据包的可靠到达,TCP有CRC校验机制来保证数据包的无差错性,UDP的CRC是可选的,TCP会重新排序乱序的数据包和丢弃重复的数据,TCP能够提供流量控制机制,使用滑动窗口算法,TCP能提供拥塞控制与恢复机制,存在多种TCP拥塞控制模型,TCP能协商发送的数据报文长度。 TCP报头。 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ TCP Header Format 对于TCP头的标记位,SYN标记只在三次握手(或四次握手)的时候的被置位,ACK标记会在握手之后所有的TCP报文中被置位。当然也有一些特殊情况,比如有些情况下RST报文不会置位ACK。这些规则也许在配置复杂的ACL中有用。 (2) TCP协议栈的状态机 (摘自RFC793)


a. 超时与重传RTT的计算与RTO的计算 b. 慢启动和拥塞避免算法慢启动算法的目的是为了保证TCP发送方发送分组的速率应该匹配收到该分组确认报文的速率,这样的设计能够应用于低速链路的广域网应用。为 了实现慢启动机制,为TCP连接增加了一个新的窗口,拥塞窗口cwnd,该窗口初始化为一个报文段(非一个字节,而是一个TCP最大传输报文段大 小,MSS)。这样一个方向上的TCP连接有两个窗口,一个是接收窗口用于接收方的流量控制,一个是拥塞窗口用于发送方的流量控制。发送方以这两个窗口中 的小值作为方式上限。 慢启动算法:指数算法,cwnd默认为1,当收到一个ack确认时候,cwnd增加为2,当收到两个ack确认时候,cwnd增加为4,接着8,... 拥塞避免算法的目的,是为了防止中间路由器由于网络拥塞引起的数据包超时或者丢包。拥塞避免算法需要用到两个变量,一个是cwnd窗口大小,一个是ssthresh慢启动阈值,对于一个给定的初始连接,cwnd为1,ssthresh为65535。当拥塞发生(超时或者重复确认),当拥塞发生时候,ssthresh被设置为cwnd和接收窗口中小值的一半,如果是超时引起的拥塞,则cwnd设置为1。 拥塞避免算法:如果cwnd大于ssthresh,每收到一个数据报文的确认,cwnd=cwnd+1/cwnd,cwnd窗口大小单位仍然是mss。 拥塞避免算法其实是和慢启动配合使用的。cwnd和ssthresh都是动态的值,虽然初始值为1和65535。当真正拥塞发生的时候,如果是超时或重复ack引起的拥塞,ssthreash会置为cwnd和接收窗口大小的一半,cwnd会降为1,然后执行慢启动算法,直到cwnd大于ssthresh的时候,执行拥塞避免算法;在慢启动算法期间和拥塞避免算法期间,TCP的发送速率都是在增长的,只是一个是指数增长方式,一个是线性增长方式。 c . 快速重传和快速恢复算法TCP连接中有两种情况会引起重复的ack,一种是乱序报文,一种是丢包。 快速重传:当发送方收到三个重复的ack后,不会进入慢启动状态,而是立刻重传丢失的报文。因为只有接收方收到新的报文段的时候,才会发送重复的ack,这表明TCP连接上仍然有数据流动,所以应该避免使用慢启动降速。 快速恢复:第一步,当收到第三个重复的ack的时候,ssthresh设置为当前cwnd的一半,重传丢失的报文。设置cwnd为ssthresh加上3倍的报文段大小(cwnd=cwnd/2 + 3)。第二步,每收到一个重复的ack,cwnd增加1并发送一个分组。第三步,当下一个确认新数据的ack到达的时候,设置cwnd为上面第一步中ssthresh值,这个ack应该是对重传报文的确认,同时也是对丢包后面的中间报文的确认。 最后,在收到三个重复ack的情况下,速度减半。 快速重传算法首次出现在4.3BSD的Tahoe版本,快速恢复首次出现在4.3BSD的Reno版本,也称之为Reno版的TCP拥塞控制算法。 可以看出Reno的快速重传算法是针对一个包的重传情况的,然而在实际中,一个重传超时可能导致许多的数据包的重传,因此当多个数据包从一个数据窗口中丢失时并且触发快速重传和快速恢复算法时,问题就产生了。因此NewReno出现了,它在Reno快速恢复的基础上稍加了修改,可以恢复一个窗口内多个包丢失的情况。具体来讲就是:Reno在收到一个新的数据的ACK时就退出了快速恢复状态了,而NewReno需要收到该窗口内所有数据包的确认后才会退出快速恢复状态,从而更一步提高吞吐量。 SACK就是改变TCP的确认机制,最初的TCP只确认当前已连续收到的数据,SACK则把乱序等信息会全部告诉对方,从而减少数据发送方重传的盲目性。比 如说序号1,2,3,5,7的数据收到了,那么普通的ACK只会确认序列号4,而SACK会把当前的5,7已经收到的信息在SACK选项里面告知对端,从 而提高性能,当使用SACK的时候,NewReno算法可以不使用,因为SACK本身携带的信息就可以使得发送方有足够的信息来知道需要重传哪些包,而不 需要重传哪些包。 (5) TCP的应用前几天和公司做防火墙限速的同事聊天, 我们公司新的防火墙限速实现方案就用到了TCP窗口机制. 作所周知, QoS除了分类,测速,队列还有调度一类的借助硬件的算法以外,在基于缓存或者丢包的限速基础上,最好还要降低TCP端到端的真正发送的速率,否则容易引 起TCP的一系列拥塞控制动作。我们软件新的设计,就是通过修改ACK方向的通告窗口大小,来控制发送发的速率,能够在限速的基础上,同时降低发送方的发 送速率。
本文出自 “jasonccie” 博客,请务必保留此出处http://jasonccie.blog.51cto.com/2143955/422966