TCP协议设计原理


 


  最近去了解TCP协议,发现这是一个特别值得深思的协议。在本篇博客中,不会长篇大论的给大家介绍TCP协议特点、包头格式以及TCP的连接和断开等基本原理,而是会带大家深入理解为什么要这么设计,如果不这么设计,会产生什么后果,希望能帮助大家对TCP协议的理解。TCP弥补了IP尽力而为服务的不足,实现了面向连接、高可靠性、报文按序到达、端到端流量控制。

  • 面向连接

  一提到TCP是面向连接的协议,必然是介绍其的3次握手和4次挥手,为了说明为什么需要三次握手和四次挥手,我们还是拿两个图来说明连接建立和断开的过程。

 

  为什么要三次握手呢?若两次握手怎样。假设客户端发起连接请求(SYN=1,seq=client_isn),服务器端收到请求后返回消息(SYN=1,seq=server_isn,ack=client+1)连接建立。

  现在说明为什么两次握手不可以。若客户端发送连接请求request1(SYN=1,seq=client_isn),这时这个请求由于网络阻塞没有及时到达服务器端,而客户端一段时间后又发送了一个连接请求request2 (SYN=1,seq=client_isn),该request2建立了连接完成了本次通信,然后断开连接。此时客户端发送的第一个连接请求request1到达了服务器端,此时服务器端发现是一个连接请求,服务端并不知道这是由于网络阻塞导致已经无用的连接请求,服务器收到request1则给客户端发送消息(SYN=1,seq=server_isn,ack=client_isn+1)。如果是两次握手那么客户端在收到这条消息后则客户端和服务器端建立连接。但客户端并不是真正想建立连接,所以不能通过两次握手就建立连接。

  那为什么需要四次挥手呢?如果三次挥手又会怎样。我们假设客户端向服务器发送了断开请求,服务器在收到断开请求后也向客户端发送断开请求(FIN=1,ACK=1,seq=w,ack=u+1),客户端收到此消息后向服务器发送断开连接(ACK=1,seq=u+1,ack=w+1)。可想而知这种方法是不可行的。因为当客户端没有数据需要发送给服务器时,客户端主动发起了断开请求,但是并不代表服务器端没有数据发给客户端。所以为了保证服务器端正常传输完数据,服务器端在收到客户端发送的断开请求后先发送一个ACK(ACK=1,seq=v,ack=u+1)给客户端,当服务器端数据传输完后发送断开请求(FIN=1,ACK=1,seq=w,ack=u+1)。

  不知道大家有没有注意到客户端在发送了最后一个断开请求的ACK后,又等待了2MSL的时间才关闭连接。为什么不直接关闭连接呢?如果客户端直接关闭连接,而此时客户端最后发送的ACK又在网络中丢失,从而可能导致服务器端的连接无法正常关闭。那为什么又要设置为2MSL呢?1MSL表示一个IP数据报在网络中的最多存活时间。假设客户端最后发送的ACK经过将近1MSL快要到达服务器端的时候丢失了,那么服务器端在规定的时间内未收到最后客户端发送的ACK,则服务器端重新发送最后的FIN给客户端,请求客户端重发ACK,该FIN经过1MSL到达客户端。所以如上最坏情况,如果客户端在2MSL内没有收到FIN请求,则表明服务器端已经断开连接。

  • 传输高可靠性

  不用多说,大家都知道TCP的传输可靠性是依据确认号实现的。简单说就是客户端每发送一个分段给服务器端,服务端收到后会给客户端发送一个确认号,表示服务器端收到该分段。如果客户端在RTT时间周期内未收到服务器端的确认号,则引发超时重传。因此TCP协议中需要计时器。那么问题就来了,TCP有那么多分段,是要给每一个分段都生成一个计时器吗?

  给每个分段都生成一个计时器当然是最简单也最好理解的,每个计时器在RTT时间后到期,如果没有收到确认号则重传该分段。然而给每个分段都生成计时器将带来巨大的内存开销和调度开销。因此在实际中采取给每个TCP连接生成一个计时器,那么问题又来了,一个TCP连接有那么多分段,如何利用一个计时器管理这么多分段呢?设计原则如下(大家可以思考一下为什么这么设计):

  1. 发送TCP分段时,如果没有开启重传定时器,则开启;
  2. 发送TCP分段时,如果有重传定时器开启,则不再开启;
  3. 收到一个非冗余的ACK时,如果有数据在传输,重新启动重传定时器;
  4. 收到一个非冗余的ACK时,如果没有数据在传输,则关闭重传定时器;
  5. 如果连续收到3个冗余ACK时,则不用等到重传定时器超时,直接重传。
  • 报文按序到达

  确认号是TCP两端通信的数据传输的“标志”,TCP的发送端在收到一个确认号后,就认为接收端已经收到了该确认号之前的所有数据。早期的TCP标准中,只要TCP有一个分段丢失,该分段后的其他分段即使正确到达接收端,发送端还是会重传丢失分段后的所有分段,从而导致了大量不必要的超时重传。现在的TCP实现了一种选择确认的方式,接收端会显示的告诉发送端重传哪些分段,不需要重传哪些分段,避免了重传风暴。

  不知道大家在学习TCP协议时,有没有考虑TCP序列号回绕的问题。从TCP报文头部知道序列号占32位,能传输2的32次方个字节。如果一个1Gbps的网络,TCP端1s会发送125MB的数据,从而在32s内可发送2的32次方个字节,导致序列号回绕,而32s是小于MSL值的。一旦序列号回绕会导致接收端对TCP报文的排序发生错乱。当然可以通过加时间戳的方式来辅助序列号的识别,在接收端发现序列号回绕时,比较时间戳字段的值,如果回绕的序列号时间戳较大,则说明确实发生了回绕,从而将该数据放在最大的序列号之后。TCP还有其他方法判断序列号是否发生回绕,从而有效的确定数据报的排列顺序。

  • 端到端流量控制

  端到端流量控制使用滑动窗口来实现,一提到滑动窗口大家张口就来的是慢开始、拥塞避免、快重传、快恢复。那么问题来了:①快重传和快恢复确实提高了TCP的传输效率,但是如果发送端每次发送的TCP报文中仅有少量的数据,而包含大量的报头字段,从而也会影响效率,那么如何增大发送端发送数据的大小呢。②接收端在收到数据后返回给发送端一个ACK,如果接收端针对每个分段都返回ACK的话,网络中的ACK也会消耗大量的带宽,那么如何减少网络中ACK的发送呢。

  大家可能看到这样的长篇大论,已经没有了任何兴趣,那就放一张卡车拉煤图吧。我想通过卡车拉煤来说明如何解决这两个问题。其中括号中的是TCP中问题用拉煤的例子解释。

  我们先说第一个问题,就是TCP每次携带数据量少(卡车每次都拉一点煤,都不够油钱的)的问题。TCP中为什么会存在这个问题呢?接收端通过ack告诉发送端接收端窗口大小,决定发送端还可以发送多少数据(北京发电厂告诉山西煤场我这最多还可以接受5kg煤,你下次就送5kg煤就可以了,然后山西煤场就真的开着卡车送来了5kg煤)。这种情况显然需要从接收端着手解决,如果接收窗口为0,则告诉发送端不要在发送数据了,只有当接收端可接受的数据达到接收窗口的一半时,再告诉发送窗口发送数据(也就是说北京发电厂已经腾出了一半的空地可放煤了,才告知山西煤场送煤)。那还存在问题,虽然接受窗口已经有一半空闲,但是发送窗口发送的TCP携带的数据量还是较少(虽然发电厂已经有一半的地可以放煤了,但是煤场每次只送5kg煤)。这就是发送端的问题了,从而利用Nagle算法解决发送端持续发送小块数据分段的问题。如下我们就来看看这个Nagle算法:

IF 数据的大小和窗口的大小都超过了MSS
Then 发送数据分段
ELSE
  IF 还有发出的不足MSS大小的TCP分段没有收到确认
    Then 积累数据到发送队列的末尾的TCP分段
  ELSE
    发送数据分段
  EndIF
EndIF

  第二个问题就是网络中ACK消耗大量带宽的问题(也就是说卡车把煤拉到北京,直接带着北京的口信,空着车就回山西了)。RFC建议了一种延迟的ACK,也就是说接收端在收到数据并不立即回复ACK,而是等一段时间,看看接收端是否也有数据要发送给发送端,同时通过要发送的数据一同传输给发送端。等一段时间,可能后续的TCP分段到达,这样就可以取最大者一起返回,从而也能减少网络中ACK的数量。当然RFC的建议延迟的ACK最多等待两个分段的积累确认。

原文地址:https://www.cnblogs.com/lcr-smg/p/10159865.html

时间: 2024-11-09 08:20:46

TCP协议设计原理的相关文章

从TCP协议的原理来谈谈rst复位攻击

在谈RST攻击前,必须先了解TCP:如何通过三次握手建立TCP连接.四次握手怎样把全双工的连接关闭掉.滑动窗口是怎么传输数据的.TCP的flag标志位里RST在哪些情况下出现.下面我会画一些尽量简化的图来表达清楚上述几点,之后再了解下RST攻击是怎么回事. 1.TCP是什么? TCP是在IP网络层之上的传输层协议,用于提供port到port面向连接的可靠的字节流传输.我来用土语解释下上面的几个关键字: port到port:IP层只管数据包从一个IP到另一个IP的传输,IP层之上的TCP层加上端口

基于优先级概率降速的最后期限可感知TCP 协议设计

DCTCP:利用显示拥赛通知(ECN)反馈机制来调整发送端的速率.使得交换机缓冲区队列长度一直维持在一个很小的长度.DCTCP帮助这些延迟敏感的流避免大的队列延迟,以至于成功获得低延迟.但是其是deadline-unware 协议.忽视了短流和背景流对不同截止时间的需求. D3:第一个截止时间知晓的传输控制协议.许多紧急的流到达的比较晚将会错过截止时间. D2TCP:根据流的紧急程度和网络拥塞状态调整滑动窗口的减少,这样来帮助紧急的流来不错过它的截止时间. PDQ:缩短了流的平均完成时间,对于截

[转帖]Linux TCP/IP协议栈,数据发送接收流程,TCP协议特点

Linux TCP/IP协议栈,数据发送接收流程,TCP协议特点 http://network.51cto.com/art/201909/603780.htm 可以毫不夸张的说现如今的互联网是基于TCP/IP构建起来的网络.弄懂协议栈的原理,无论对调试网络IO性能还是解决网络问题都是有很大帮助的.本片文章就带领大家来看看内核是如何控制网络数据流的. 作者:底层软件架构来源:今日头条|2019-09-30 09:28 收藏 分享 可以毫不夸张的说现如今的互联网是基于TCP/IP构建起来的网络.弄懂

浅析低延迟直播协议设计:RTP/RTCP

转自:http://blog.csdn.net/dj0379/article/details/51960237 如今的直播市场非常火爆,有很多直播云服务的提供商可供产品选择.同时视频直播产品喷涌而出,比如大家耳熟能详的映客.YY,还有最近特别火爆的一直播. 基于TCP的协议延迟不够低 众所周知,直播中通用CDN大部分提供的是RTMP的方案以及HLS的方案.HLS在手机H5里面的兼容性非常好,而RTMP是Adobe的协议,它在延迟.稳定性和分发质量方面平衡得很不错.但是当涉及会议场景时,基于TCP

TCP协议可靠性数据传输实现原理分析

http://blog.csdn.net/chexlong/article/details/6123087 TCP 协议是一种面向连接的,为不同主机进程间提供可靠数据传输的协议.TCP 协议假定其所使用的网络栈下层协议(如IP 协议)是非可靠的,其自身提供机制保证数据的可靠性传输.在目前的网络栈协议族中,在需要提供可靠性数据传输的应用中,TCP 协议是首选的,有时也是唯一的选择.TCP 协议是在最早由Cerf 和Kahn[1]所提出的有关网络数据包传输协议的概念之上建立的.TCP 协议被设计成符

主程序员的练成:TCP、消息分包和协议设计

在<主程序员的练成:IP.DNS和CDN>中,一次网络请求经过DNS解析知道了目的IP,现在就要发出网络包,这里我们说一说TCP的相关话题. TCP是一种流式协议 讲网络编程的教科书一般都会对TCP的可靠传输,api用法做详细说明,但对于TCP是一种流式协议讲解的不多,但这背后隐藏着很重要的一个知识点.先做个名词定义方便交流,这里的"消息"是指应用层的一个完整的协议包. 流式协议的特点是什么?就像流水连续不断那样,消息之间没有边界.例如send了3条消息,分别是100字节.

TCP/IP协议工作原理简述

TCP/IP协议工作原理简述 Table of Contents 1 概要 2 应用层 3 传输层 4 网络层 5 链路层 1 概要 协议是什么?协议是一组为完成特定需求或功能而定义的标准通讯格式.协议是服务于具体需求或功能的,它不能独立存在. 制定TCP/IP协议的目的是为了解决主机互联以及互联的主机上的应用通讯的问题.TCP/IP协议共有四层:应用层.传输层.网络层.链路层.应用层实际就是我们的应用程序,对于非具体应用而言这一层的协议是未定义的,需要我们自己根据我们具体的业务模型来制定.传输

TCP/IP 协议工作原理与Linux系统下调优

TCP/IP建立连接的三次握手过程: 建立TCP连接共需要三个packet Client--> syn=1,ack=0,fin=0 -->  Server Client<--  syn=1,ack=1,fin=0 <--  Server Client-->  syn=0,ack=1,fin=0 -->  Server TCP/IP关闭连接的四个过程: 关闭TCP连接需要四个packet: Client-->  FIN  -->  Server Client&

TCP协议,UDP协议,Utp,双绞线,DHCP协议,子网掩码,LAN,VLAN,网口,服务器,UI设计,Linux系统,Unix系统,名词解释

TCP协议: TCP:Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的.可靠的.基于字节流的运输层(Transport layer)通信协议,由IETF的RFC 793说明(specified).在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,UDP是同一层内另一个重要的传输协议. UDP协议: UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Int