详解 TCP(上)
让我们来看看这张图首先来了解每个部分的意义其他部分解释在这里:为什么建链接要 3 次握手,断链接需要 4 次挥手?另有一些需要注意的地方:Again,使用tcp_tw_reuse和tcp_tw_recycle来解决TIME_WAIT的问题是非常非常危险的,因为这两个参数违反了TCP协议(RFC 1122)SeqNum 的增加是和传输的字节数相关的。上图中,三次握手后,来了两个 Len:1440 的包,而第二个包的 SeqNum 就成了 1441。然后第一个 ACK 回的是 1441,表示第一个 1440 收到了。注意:如果你用 Wireshark 抓包程序看 3 次握手,你会发现 SeqNum 总是为 0,不是这样的,Wireshark 为了显示更友好,使用了 Relative SeqNum ——相对序号,你只要在右键菜单中的 protocol preference 中取消掉就可以看到“Absolute SeqNum”了TCP 要保证所有的数据包都可以到达,所以,必需要有重传机制。比如:发送端发了 1,2,3,4,5 五个包,接收端收到了 1,2 于是返回 ack 3,然后收到了 4(3 没收到)。此时的 TCP 会怎么办?因为正如前面所说的,SeqNum 和 Ack 是以字节数为单位,所以 ack 的时候,不能跳着确认,只能确认最大的连续收到的包,不然,发送端就以为之前的都收到了。有这样一个简单的办法:不回 ack,死等 3。当发送方发现收不到 3 的 ack 超时后,会重传 3。一旦接收方收到 3 后,会 ack 回 4——意味着 3 和 4 都收到了。但是这样有个非常大的 BUG,不回 ACK 那收到的 4,5 也不告诉发送方,这样发送方很有可能会认为 4,5 也没有到。导致 4,5 的重传于是,TCP引入了一种叫Fast Retransmit的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就 ack 最后那个可能被丢了的包,如果发送方连续收到 3 次相同的ack,就重传。Fast Retransmit 的好处是不用等 timeout 了再重传。比如说:我收到了 3 没收到 2,返回 ack2我又收到了 4 但还是没收到 2,返回 ack2但是 TMD 我又收到了 5 就是没收到 2,还是返回 ack2这个时候,不用等 timeout 的发送方就知道了 2 怕是掉了。于是会重新发 2。然后我接收到了我就返回 ack6**快速重传只解决了一个问题:不再需要等 timeout 就可以重新传包了。那重传多少呢?我知道 4 丢了,那要不要重传 5,6,7 呢? **所以就有了另一个更好的办法:Selective Acknowledgment (SACK)。这种方式需要在 TCP 头里加一个 SACK 的东西,ACK 还是 Fast Retransmit 的 ACK,SACK 则是汇报收到的数据碎版。参看下图:这样,在发送端就可以根据回传的 SACK 知道哪些数据到了,哪些数据没有到。于是就优化了 Fast Retransmit 的算法。当然,这个协议需要两边都支持。在 Linux下,可以通过tcp_sack参数打开这个功能(Linux 2.4后默认打开)。这里还需要注意一个问题——接收方 Reneging,所谓 Reneging 的意思就是接收方有权把已经报给发送端 SACK 里的数据给丢了。这样干是不被鼓励的,因为这个事会把问题复杂化了,但是,接收方这么做可能会有些极端情况,比如要把内存给别的更重要的东西。所以,发送方也不能完全依赖 SACK,还是要依赖 ACK,并维护 Time-Out,如果后续的 ACK 没有增长,那么还是要把 SACK 的东西重传,另外,接收端这边永远不能把 SACK 的包标记为 Ack。注意:SACK 会消费发送方的资源,试想,如果一个攻击者给数据发送方发一堆 SACK 的选项,这会导致发送方开始要重传甚至遍历已经发出的数据,这会消耗很多发送端的资源。详细的东西请参看《 TCP SACK的性能权衡 》Duplicate SACK 又称 D-SACK,其主要使用了 SACK 来告诉发送方有哪些数据被重复接收了。D-SACK 使用了 SACK 的第一个段来做标志下面的示例中,丢了两个 ACK,所以,发送端重传了第一个数据包(3000-3499),于是接收端发现重复收到,于是回了一个SACK=3000-3500,因为 ACK 都到了 4000 意味着收到了 4000 之前的所有数据,所以这个 SACK 就是 D-SACK——旨在告诉发送端我收到了重复的数据,而且我们的发送端还知道,数据包没有丢,丢的是 ACK 包。下面的示例中,网络包(1000-1499)被网络给延误了,导致发送方没有收到 ACK,而后面到达的三个包触发了“Fast Retransmit算法”,所以重传,但重传时,被延误的包又到了,所以,回了一个SACK=1000-1500,因为 ACK 已到了3000,所以,这个 SACK 是D-SACK——标识收到了重复的包。这个案例下,发送端知道之前因为“Fast Retransmit算法”触发的重传不是因为发出去的包丢了,也不是因为回应的 ACK 包丢了,而是因为网络延时了。可见,引入了D-SACK,有这么几个好处:知道这些东西可以很好得帮助TCP了解网络情况,从而可以更好的做网络上的流控。Linux 下的 tcp_dsack 参数用于开启这个功能(Linux 2.4后默认打开)陈皓大神讲的真的非常非常好,我仔仔细细把这篇文章过了一遍。

TCP/IP详解——链路层
以太网的链路层协议:两个串行接口链路层协议(SLIP 和PPP), 以及大多数实现都包含的环回(loopback)驱动程序。 MTU: 最大传输单元2.2. 以太网和IEEE 802封装 ——我们常说的都是以太网的封装格式(常用)以 太 网 这 个 术 语 一 般 是 指 数 字 设 备 公 司 ( D i g i t a l E q u i p m e n t C o r p . )、 英 特 尔 公 司 ( I n t e l C o r p . )和 X e r o x 公司在 1 9 8 2 年 联 合 公 布 的 一 个 标 准 。8 0 2 . 3 针对整个 C S M A / C D 网络,8 0 2 . 4 针 对 令 牌 总 线 网 络 ,8 0 2 . 5 针 对 令 牌 环 网 络 。都是由 8 0 2 . 2标 准 来 定 义 , 那 就 是 8 0 2 网 络 共 有 的 逻 辑 链 路 控 制 ( L L C )。 不 幸 的 是 , 8 0 2 . 2 和 8 0 2 . 3 定 义 了 一 个 与 以 太 网 不 同 的 帧 格 式 。IEEE 802要求每台Internet主机都与一个10Mb/s的以太网电缆相连接的:1)必须能发送和接收采用REC 1042(IEEE 802)封装格式的分组2)应该能够接收与RFC 894 混合的REC 1042封装格式的分组3)也许能够发送采用 RFC 1042格式封装的分组。如果主机能同时发送两种类型的分组数据,那么发送的分组必须是可以设置的,而且默认条件下必须是 RFC 894分组。RFC 894 和 RFC 1042两种帧格式都采用 4 8 b i t ( 6 字节)的目的地址和源地址( 8 0 2 . 3 允许使用 1 6 b i t 的地址,但一般是 4 8 b i t 地址)。这就是我们在本书中所称的硬件地址。 A R P 和 R A R P 协议(第4 章和第 5 章) 对 3 2 b i t 的 I P 地址和 4 8 b i t 的 硬 件 地 址 进 行 映 射 。C R C 字 段 用 于 帧 内 后 续 字 节 差 错 的 循 环 冗 余 码 检 验 ( 检 验 和 )( 它 也 被 称 为 F C S 或帧检验序列)。 —— 这个需要看一下这个是怎么校验的2.3 尾部封装描述了另一种用于以太网的封装格式,称为:尾部封装(trailer encapsulation)通过调整IP数据包中字段的次序来提高性能。《在以太网中数据帧中,开始的那部分是边长的字段(IP首部和TCP首部)》把它们移到尾部(在CRC之前),这样当把数据复制到内核时,就可以把数据帧中的数据部分映射到一个硬件页面, 节省内存到内存的复制过程。TCP 数据报的长度是512字节的整数倍,正好可以用内核中的页表处理。 —— 所以,我们要了解内存的分页过程—— 现在基本上是反对了尾部封装了; (可以略过)2.4 SLIP: 串行线路IP(Serial Line IP)它是一种在串行线路上对IP数据报进行封装的简单形式。SLIP适用于家庭中每台计算机几乎都有的RS-232串行端口和高速调制解调器接入Internet。SLIP 缺陷:1)每一端必须知道对方的 I P 地址。没有办法把本端的 I P 地址通知给另一端。2)数 据 帧 中 没 有 类 型 字 段 ( 类 似 于 以 太 网 中 的 类 型 字 段 )。如果一条串行线路用于 S L I P ,那么它不能同时使用其他协议3)S L I P 没 有 在 数 据 帧 中 加 上 检 验 和 ( 类 似 于 以 太 网 中 的 C R C 字段)。如果 S L I P 传 输 的 报 文被线路噪声影响而发生错误,只能通过上层协议来发现(另一种方法是,新型的调制解调 器 可 以 检 测 并 纠 正 错 误 报 文 )现在很多厂家都支持这个协议;2.5 压缩的SLIP由 于 串 行 线 路 的 速 率 通 常 较 低 ( 1 9 2 0 0 b / s 或 更 低 ), 而 且 通 信 经 常 是 交 互 式 的 ( 如 T e l n e t 和 R l o g i n , 二 者 都 使 用 T C P ),因此在 S L I P 线 路 上 有 许 多 小 的 T C P 分 组 进 行 交 换 。 为 了 传 送 1 个 字 节 的 数 据 需 要 2 0 个字节的 I P 首部和 2 0 个字节的 T C P 首 部 , 总 数 超 过 4 0 个字节;C S L I P 一般能把上面的 4 0 个字节压缩到 3 或 5 个 字节。2.6 PPP 点对点协议修改了SLIP协议的所有缺陷包括了三个部分:1)在串行链路上封装IP数据包的方法。支持数据为8bit和无奇偶校验的异步模式,还支持面向比特的同步链接2)建立、配置及测试数据链路的链路控制协议(TCP:Link Control Protocol) 。 它允许通信双方进行协商,已确定不同的选项。3)针对不同的网络层协议的网络控制协议(NCP:Network Control Protocol)体系。当前RFC定义的网络层有IP、OSI网络层、DECnet以及AppleTalk。每一帧都以标志字符 0 x 7 e 开始和结束。紧接着是一个地址字节,值始终是 0 x ff ,然后是一 个值为 0 x 0 3 的控制字节。信息中如果有0x7E , 那么就需要采用比特填充(bit stuffing)的硬件技术来完成的;2.7 环回接口 (lookback interface)允许运行在同一台主机上的客户程序和服务程序通过TCP/IP 进行通信。A类网络号127就是给环回接口预留的;一般系统把IP地址127.0.0.1 分配给这个接口,并命名为localhost。 一个传给环回的IP数据包不能在任何网络上出现。检测到目的端地址是环回地址时,应该可以省略部分传输层和所 有网络层的逻辑操作。但是大多数的产品还是照样完成传输层和网络层的所有过程,只是当I P 数据报离开网络层时把它返回给自己。2.8 最大传输单元MTU链路上对数据帧的长度都有一个限制的特性 —— MTU如果 I P 层 有 一 个 数 据 报 要 传 , 而 且 数 据的长度比链路层的 M T U 还大,那么 I P 层 就 需 要 进 行 分 片 ( f r a g m e n t a t i o n ), 把 数 据 报分成若干片,这样每一片都小于 M T U 。点到点的链路层(如 S L I P 和 P P P )的 M T U并非指的 是网络媒体的物理特性。相反,它是一个逻辑限制,目的是为交互使用提供足够快的响应时 间。2.9 路径MTU当在同一个网络上的两台主机互相进行通信时,该网络的 M T U 是 非 常 重 要 的 。但 是 如 果 两台主机之间的通信要通过多个网络,那么每个网络的链路层就可能有不同的 M T U 。重要的不是两台主机所在网络的 M T U的值,重要的是两台通信主机路径中的最小 M T U 。它被称作路径M T U。两台主机之间的路径 M T U 不 一 定 是 个 常 数 。 它 取 决 于 当 时 所 选 择 的 路 由 。 而 选 路 不 一 定 是 对 称 的 ( 从 A 到 B 的 路 由 可 能 与 从 B 到 A 的 路 由 不 同 ), 因 此 路 径 M T U 在 两 个 方 向 上 不 一 定 是 一致的。——> 动态、方向2.10 串行线路吞吐量计算将用这些串行线路吞吐量的计算来验证数据从串行线路上通过的 时间。数据块的划分: 考虑到数据的占用比例,和等待的时间问题,取一个平衡的值; 。。。。 这个需要进行计算

TCP连接详解
通过设置linux参数 net.ipv4.tcp_fin_timeout = 30 ,可以调整如发现系统存在大量TIME_WAIT状态的连接,通过调整内核参数解决:编辑文件/etc/sysctl.conf,加入以下内容tcp 通过序列号seq记录已经发送的数据刻度,通过ack记录已经接收的数据量。seq记录的是发送的数据,ack记录的是接收的数据量。单位是字节(8bit)tcp在每次发包时都会计算往复时间及其偏差。将这个往返时间和偏差相加,重发超时时间就是比这个总和要稍大一点的值。由于最初的数据包还不知道往返时间,所以其重发超时一般设置为6s左右。在建立tcp连接时,三次握手的时候会计算mss(最大消息长度),建立连接的双方会把自己的接口能适应的mss值放到tcp首部里面发送给对方,最后取较小的那个mss。tcp窗口大小指的是无需等待确认应答而可以继续发送数据的最大值,窗口大小为4个端。即在收到确认应答之前可以发送的数据的段数。接收端没有按序列顺序收到数据端时,会不停的发送确认应答,并将当前收到的顺序出问题的数据放到缓冲区。发送端连续三次收到相同序列号的数据段时,会重新发送该段的数据。接收端在接收到遗失的数据的时候会将数据与缓冲区的数据组合,重新按顺序确定ack的序列号,继续接收数据。tcp窗口的大小是由接收端的处理能力决定的,接收端会在ack的tcp首部中将能处理的窗口大小传给发送端。拥塞窗口是限制每次发送的数据的大小,初始值是1mss,也就是慢启动。随着正常的收发的进行,拥塞窗口的值会不断的增加。但是不会超过接收端处理窗口的大小。一开始拥塞窗口每次都会翻倍的增长,在超过慢启动阈值后增长速度会减慢。增长速率=一个数据段的大小 / 拥塞窗口的大小 *一个数据段的大小超时重发时,拥塞窗口会变为1mss, 慢启动阈值为原有窗口的一半重复确认应答时,慢启动阈值为原有窗口的一半,拥塞窗口会变为慢启动阈值+3数据端,1、已发送的数据收到了ack回执2、可以发送mss大小的数据时只有以上两个数据都满足时才发送数据。会有延迟,对延迟敏感的需求可以关。1、收到2*最大端长度的数据2、最大延迟0.5s发送确认应答将tcp的确认应答和回执数据通过一个包发送。接收数据之后等待应用处理生成返回数据以后在发送回复时同时发送回执。需要开启延迟确认应答。

TCP协议详解及实战解析【精心整理收藏】
TCP协议是在TCP/IP协议模型中的运输层中很重要的一个协议、负责处理主机端口层面之间的数据传输。主要有以下特点:1.TCP是面向链接的协议,在数据传输之前需要通过三次握手建立TCP链接,当数据传递完成之后,需要通过四次挥手进行连接释放。2.每一条TCP通信都是两台主机和主机之间的,是点对点传输的协议。3.TCP提供可靠的、无差错、不丢失、不重复,按序到达的服务。4.TCP的通信双方在连接建立的任何时候都可以发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。5.面向字节流。在数据传输的过程中如果报文比较长的话TCP会进行数据分段传输,每一条分段的TCP传输信息都带有分段的序号,每一段都包含一部分字节流。接收方根据每段携带的的序号信息进行数据拼接,最终拼接出来初始的传输数据。但是在整个传输的过程中每一段TCP携带的都是被切割的字节流数据。所以说TCP是面向字节流的。a.TCP和UDP在发送报文时所采用的方式完全不同。TCP并不关心应用程序一次把多长的报文发送到TCP缓存中,而是根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应包含多少个字节(UDP发送的报文长度是应用程序给出的)。b.如果应用程序传送到TCP缓存的数据块太大,TCP就可以把它划分短一些再传。TCP也可以等待积累有足够多的字节后再构建成报文段发送出去。各字段含义:源端口:发送端的端口号目的端口:接收端的端口号序号:TCP将发送报文分段传输的时候会给每一段加上序号,接收端也可以根据这个序号来判断数据拼接的顺序,主要用来解决网络报乱序的问题确认号:确认号为接收端收到数据之后进行排序确认以及发送下一次期待接收到的序号,数值 = 接收到的发送号 + 1数据偏移:占4比特,表示数据开始的地方离TCP段的起始处有多远。实际上就是TCP段首部的长度。由于首部长度不固定,因此数据偏移字段是必要的。数据偏移以32位为长度单位,因此TCP首部的最大长度是60(15*4)个字节。控制位:URG:此标志表示TCP包的紧急指针域有效,用来保证TCP连接不被中断,并且督促 中间层设备要尽快处理这些数据;ACK:此标志表示应答域有效,就是说前面所说的TCP应答号将会包含在TCP数据包中;有两个取值:0和1, 为1的时候表示应答域有效,反之为0;PSH:这个标志位表示Push操作。所谓Push操作就是指在数据包到达接收端以后,立即传送给应用程序, 而不是在缓冲区中排队;RST:这个标志表示连接复位请求。用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据包;SYN:表示同步序号,用来建立连接。SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1, ACK=0;连接被响应的时候,SYN=1,ACK=1;这个标志的数据包经常被用来进行端口扫描。扫描者发送 一个只有SYN的数据包,如果对方主机响应了一个数据包回来 ,就表明这台主机存在这个端口;但是由于这 种扫描方式只是进行TCP三次握手的第一次握手,因此这种扫描的成功表示被扫描的机器不很安全,一台安全 的主机将会强制要求一个连接严格的进行TCP的三次握手;FIN: 表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志 位的TCP数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。窗口:TCP里很重要的一个机制,占2字节,表示报文段发送方期望接收的字节数,可接收的序号范围是从接收方的确认号开始到确认号加上窗口大小之间的数据。后面会有实例讲解。校验和:校验和包含了伪首部、TCP首部和数据,校验和是TCP强制要求的,由发送方计算,接收方验证紧急指针:URG标志为1时,紧急指针有效,表示数据需要优先处理。紧急指针指出在TCP段中的紧急数据的最后一个字节的序号,使接收方可以知道紧急数据共有多长。选项:最常用的选项是最大段大小(Maximum Segment Size,MSS),向对方通知本机可以接收的最大TCP段长度。MSS选项只在建立连接的请求中发送。放在以太网帧里看TCP的位置TCP 数据包在 IP 数据包的负载里面。它的头信息最少也需要20字节,因此 TCP 数据包的最大负载是 1480 - 20 = 1460 字节。由于 IP 和 TCP 协议往往有额外的头信息,所以 TCP 负载实际为1400字节左右。因此,一条1500字节的信息需要两个 TCP 数据包。HTTP/2 协议的一大改进, 就是压缩 HTTP 协议的头信息,使得一个 HTTP 请求可以放在一个 TCP 数据包里面,而不是分成多个,这样就提高了速度。以太网数据包的负载是1500字节,TCP 数据包的负载在1400字节左右一个包1400字节,那么一次性发送大量数据,就必须分成多个包。比如,一个 10MB 的文件,需要发送7100多个包。发送的时候,TCP 协议为每个包编号(sequence number,简称 SEQ),以便接收的一方按照顺序还原。万一发生丢包,也可以知道丢失的是哪一个包。第一个包的编号是一个随机数。为了便于理解,这里就把它称为1号包。假定这个包的负载长度是100字节,那么可以推算出下一个包的编号应该是101。这就是说,每个数据包都可以得到两个编号:自身的编号,以及下一个包的编号。接收方由此知道,应该按照什么顺序将它们还原成原始文件。收到 TCP 数据包以后,组装还原是操作系统完成的。应用程序不会直接处理 TCP 数据包。对于应用程序来说,不用关心数据通信的细节。除非线路异常,否则收到的总是完整的数据。应用程序需要的数据放在 TCP 数据包里面,有自己的格式(比如 HTTP 协议)。TCP 并没有提供任何机制,表示原始文件的大小,这由应用层的协议来规定。比如,HTTP 协议就有一个头信息Content-Length,表示信息体的大小。对于操作系统来说,就是持续地接收 TCP 数据包,将它们按照顺序组装好,一个包都不少。操作系统不会去处理 TCP 数据包里面的数据。一旦组装好 TCP 数据包,就把它们转交给应用程序。TCP 数据包里面有一个端口(port)参数,就是用来指定转交给监听该端口的应用程序。应用程序收到组装好的原始数据,以浏览器为例,就会根据 HTTP 协议的Content-Length字段正确读出一段段的数据。这也意味着,一次 TCP 通信可以包括多个 HTTP 通信。服务器发送数据包,当然越快越好,最好一次性全发出去。但是,发得太快,就有可能丢包。带宽小、路由器过热、缓存溢出等许多因素都会导致丢包。线路不好的话,发得越快,丢得越多。最理想的状态是,在线路允许的情况下,达到最高速率。但是我们怎么知道,对方线路的理想速率是多少呢?答案就是慢慢试。TCP 协议为了做到效率与可靠性的统一,设计了一个慢启动(slow start)机制。开始的时候,发送得较慢,然后根据丢包的情况,调整速率:如果不丢包,就加快发送速度;如果丢包,就降低发送速度。Linux 内核里面 设定 了(常量TCP_INIT_CWND),刚开始通信的时候,发送方一次性发送10个数据包,即"发送窗口"的大小为10。然后停下来,等待接收方的确认,再继续发送。默认情况下,接收方每收到 两个TCP 数据包,就要 发送 一个确认消息。"确认"的英语是 acknowledgement,所以这个确认消息就简称 ACK。ACK 携带两个信息。发送方有了这两个信息,再加上自己已经发出的数据包的最新编号,就会推测出接收方大概的接收速度,从而降低或增加发送速率。这被称为"发送窗口",这个窗口的大小是可变的。注意,由于 TCP 通信是双向的,所以双方都需要发送 ACK。两方的窗口大小,很可能是不一样的。而且 ACK 只是很简单的几个字段,通常与数据合并在一个数据包里面发送。即使对于带宽很大、线路很好的连接,TCP 也总是从10个数据包开始慢慢试,过了一段时间以后,才达到最高的传输速率。这就是 TCP 的慢启动。TCP 协议可以保证数据通信的完整性,这是怎么做到的?前面说过,每一个数据包都带有下一个数据包的编号。如果下一个数据包没有收到,那么 ACK 的编号就不会发生变化。举例来说,现在收到了4号包,但是没有收到5号包。ACK 就会记录,期待收到5号包。过了一段时间,5号包收到了,那么下一轮 ACK 会更新编号。如果5号包还是没收到,但是收到了6号包或7号包,那么 ACK 里面的编号不会变化,总是显示5号包。这会导致大量重复内容的 ACK。如果发送方发现收到 三个 连续的重复 ACK,或者超时了还没有收到任何 ACK,就会确认丢包,即5号包遗失了,从而再次发送这个包。通过这种机制,TCP 保证了不会有数据包丢失。TCP是一个滑动窗口协议,即一个TCP连接的发送端在某个时刻能发多少数据是由滑动窗口控制的,而滑动窗口的大小实际上是由两个窗口共同决定的,一个是接收端的通告窗口,这个窗口值在TCP协议头部信息中有,会随着数据的ACK包发送给发送端,这个值表示的是在接收端的TCP协议缓存中还有多少剩余空间,发送端必须保证发送的数据不超过这个剩余空间以免造成缓冲区溢出,这个窗口是接收端用来进行流量限制的,在传输过程中,通告窗口大小与接收端的进程取出数据的快慢有关。另一个窗口是发送端的拥塞窗口(Congestion window),由发送端维护这个值,在协议头部信息中没有,滑动窗口的大小就是通告窗口和拥塞窗口的较小值,所以拥塞窗口也看做是发送端用来进行流量控制的窗口。滑动窗口的左边沿向右移动称为窗口合拢,发生在发送的数据被确认时(此时,表明数据已被接收端收到,不会再被需要重传,可以从发送端的发送缓存中清除了),滑动窗口的右边沿向右移动称为窗口张开,发生在接收进程从接收端协议缓存中取出数据时。随着发送端不断收到的被发送数据的ACK包,根据ACK包中的确认序号和通告窗口大小使滑动窗口得以不断的合拢和张开,形成滑动窗口的向前滑动。如果接收进程一直不取数据,则会出现0窗口现象,即滑动窗口左边沿与右边沿重合,此时窗口大小为0,就无法再发送数据。在TCP里,接收端(B)会给发送端(A)报一个窗口的大小,叫Advertised window。1.在没有收到B的确认情况下,A可以连续把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。2.发送窗口里面的序号表示允许发送的序号。显然,窗口越大,发送方就可以在收到对方确认之前连续发送更多数据,因而可能获得更高的传输效率。但接收方必须来得及处理这些收到的数据。3.发送窗口后沿的后面部分表示已发送且已收到确认。这些数据显然不需要再保留了。4.发送窗口前沿的前面部分表示不允许发送的,应为接收方都没有为这部分数据保留临时存放的缓存空间。5.发送窗口后沿的变化情况有两种:不动(没有收到新的确认)和前移(收到了新的确认)6.发送窗口前沿的变化情况有两种:不断向前移或可能不动(没收到新的确认)TCP的发送方在规定时间内没有收到确认就要重传已发送的报文段。这种重传的概念很简单,但重传时间的选择确是TCP最复杂的问题之一。TCP采用了一种自适应算法,它记录一个报文段发出的时间,以及收到响应的确认的时间这两个时间之差就是报文段的往返时间RTT。TCP保留了RTT的一个加权平均往返时间。超时重传时间RTO略大于加权平均往返时间RTT:即Round Trip Time,表示从发送端到接收端的一去一回需要的时间,tcp在数据传输过程中会对RTT进行采样(即对发送的数据包及其ACK的时间差进行测量,并根据测量值更新RTT值,具体的算法TCPIP详解里面有),TCP根据得到的RTT值更新RTO值,即Retransmission TimeOut,就是重传间隔,发送端对每个发出的数据包进行计时,如果在RTO时间内没有收到所发出的数据包的对应ACK,则任务数据包丢失,将重传数据。一般RTO值都比采样得到的RTT值要大。如果收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经正确到达接收方的数据?答案是可以的,选择确认就是一种可行的处理方法。如果要使用选项确认SACK,那么在建立TCP连接时,就要在TCP首部的选项中加上“允许SACK”的选项,而双方必须都事先商定好。如果使用选择确认,那么原来首部中的“确认号字段”的用法仍然不变。SACK文档并没有明确发送方应当怎么响应SACK.因此大多数的实现还是重传所有未被确认的数据块。一般说来,我们总是希望数据传输的更快一些,但如果发送方把数据发送的过快,接收方就可能来不及接收,这会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。在计算机网络中的链路容量,交换节点中的缓存和处理机等,都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫做拥塞。拥塞控制方法:1.慢开始和拥塞避免2.快重传和快恢复3.随机早期检测1.一开始,客户端和服务端都处于CLOSED状态2.先是服务端主动监听某个端口,处于LISTEN状态(比如服务端启动,开始监听)。3.客户端主动发起连接SYN,之后处于SYN-SENT状态(第一次握手,发送 SYN = 1 ACK = 0 seq = x ack = 0)。4.服务端收到发起的连接,返回SYN,并且ACK客户端的SYN,之后处于SYN-RCVD状态(第二次握手,发送 SYN = 1 ACK = 1 seq = y ack = x + 1)。5.客户端收到服务端发送的SYN和ACK之后,发送ACK的ACK,之后处于ESTABLISHED状态(第三次握手,发送 SYN = 0 ACK = 1 seq = x + 1 ack = y + 1)。6.服务端收到客户端的ACK之后,处于ESTABLISHED状态。(需要注意的是,有可能X和Y是相等的,可能都是0,因为他们代表了各自发送报文段的序号。)TCP连接释放四次挥手1.当前A和B都处于ESTAB-LISHED状态。2.A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。3.B收到连接释放报文段后即发出确认,然后B进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时TCP连接处于半关闭状态,即A已经没有数据发送了。从B到A这个方向的连接并未关闭,这个状态可能会持续一些时间。4.A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文端。5.若B已经没有向A发送的数据,B发出连接释放信号,这时B进入LAST-ACK(最后确认)状态等待A的确认。6.A再收到B的连接释放消息后,必须对此发出确认,然后进入TIME-WAIT(时间等待)状态。请注意,现在TCP连接还没有释放掉,必须经过时间等待计时器(TIME-WAIT timer)设置的时间2MSL后,A才进入CLOSED状态。7。B收到A发出的确认消息后,进入CLOSED状态。以请求百度为例,看一下三次握手真实数据的TCP连接建立过程我们再来看四次挥手。TCP断开连接时,会有四次挥手过程,标志位是FIN,我们在封包列表中找到对应位置,理论上应该找到4个数据包,但我试了好几次,实际只抓到3个数据包。查了相关资料,说是因为服务器端在给客户端传回的过程中,将两个连续发送的包进行了合并。因此下面会按照合并后的三次挥手解释,若有错误之处请指出。第一步,当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)。第二步,主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。第三步,主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段。第四步,主机A收到这个FIN报文段后,向主机B发送一个ACK表示连接彻底释放。这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。原因有二:一、保证TCP协议的全双工连接能够可靠关闭二、保证这次连接的重复数据段从网络中消失先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。硬件速度网络和服务器的负载请求和响应报文的尺寸客户端和服务器之间的距离TCP 协议的技术复杂性TCP 连接建立握手;TCP 慢启动拥塞控制;数据聚集的 Nagle 算法;用于捎带确认的 TCP 延迟确认算法;TIME_WAIT 时延和端口耗尽。介绍完毕,就这?是的,就这。补充:大部分内容为网络整理,方便自己学习回顾,参考文章:TCP 协议简介TCP协议图文详解什么是TCP协议?wireshark抓包分析——TCP/IP协议TCP协议的三次握手和四次挥手TCP协议详解TCP带宽和时延的研究(1)

网络传输协议的TCP/IP详解
TCP/IP是“transmission Control Protocol/Internet Protocol”的简写,中文译名为传输控制协议/互联网络协议)协议, TCP/IP(传输控制协议/网间协议)是一种网络通信协议,它规范了网络上的所有通信设备,尤其是一个主机与另一个主机之间的数据往来格式以及传送方式。TCP/IP是INTERNET的基础协议,也是一种电脑数据打包和寻址的标准方法。在数据传送中,可以形象地理解为有两个信封,TCP和IP就像是信封,要传递的信息被划分成若干段,每一段塞入一个TCP信封,并在该信封面上记录有分段号的信息,再将TCP信封塞入IP大信封,发送上网。在接受端,一个TCP软件包收集信封,抽出数据,按发送前的顺序还原,并加以校验,若发现差错,TCP将会要求重发。因此,TCP/IP在INTERNET中几乎可以无差错地传送数据。 对普通用户来说,并不需要了解网络协议的整个结构,仅需了解IP的地址格式,即可与世界各地进行网络通信。 WAPI是WLAN Authentication and Privacy Infrastructure的英文缩写。 它像红外线、蓝牙、GPRS、CDMA1X等协议一样,是无线传输协议的一种,只不过跟它们不同的是它是无线局域网(WLAN)中的一种传输协议而已,它与现行的802.11B传输协议比较相近。

本文由 在线网速测试 整理编辑,转载请注明出处。