TCP & UDP特点和区别 、TCP连接复用
重点掌握: TCP & UDP特点和区别 、TCP连接复用
# TCP
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
# 特点
面向连接的运输层协议
- 使用TCP协议之前,必须先建立TCP连接
- 传送数据完毕,必须释放已经建立的TCP连接
每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点。
连接端点脚套接字(socket)或插口:端口号拼接 到IP地址构成套接字,套接字 socket = (IP地址 :端口号)
提供可靠交付的服务。
传送的数据特点:
- 无差错
- 不丢失
- 不重复
- 按序到达
提供全双工通信
允许双方的应用进程在任何时候都能发送消息。连接两端设有发送缓存和接收缓存,用来临时存放双向通信的数据
面向字节流
流:流入到进程或进程流程的字节序列。虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序叫下来但数据看成仅仅是一连串无结构的字节流
# TCP报文段的首部格式
![首部格式](/img/browser/首部格式. png)
# 源端口和目的端口
各占2个字节,分别写入源端口和目的端口。
# 序号
占4字节。序号范围是【0,2^32 - 1】,共2^32(即4294967296)个序号。序号增加到2^32-1后,下一个序号就又回到0。也就是说,序号使用mod 2^32运算。
一报文段的序号是301,而接待的数据共有100字节。这就表明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。显然,下一个报文段(如果还有的话)的数据序号应当从401开始,即下一个报文段的序号字段值应为401。这个字段的序号也叫“报文段序号”。
# 确认号
占4字节,是期望收到对方下一个报文段的第一个数据字节的序号。 若确认号为= N,则表明:到序号N-1为止的所有数据都已正确收到。
B正确收到了A发送过来的一个报文段,其序号字段值是501,而数据长度是200字节(序号501~700),这表明B正确收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701。注意,现在确认号不是501,也不是700,而是701。
# 数据偏移
占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。由于首部中还有长度不确定的选项字段,因此数据偏移字段是必要的。
“数据偏移”的单位是32位字(即以4字节的字为计算单位)。由于4位二进制数能表示的最大十进制数字是15,因此数据偏移的最大值是60字节,这也是TCP首部的最大字节(即选项长度不能超过40字节)。
# 保留
占6位,保留为今后使用,但目前应置为0 。
# 紧急URG(URGent)
当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快发送(相当于高优先级的数据),而不要按原来的排队顺序来传送。
当URG置为1时,发送应用进程就告诉发送方的TCP有紧急数据要传送。于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍然是普通数据。这时要与首部中紧急指针(Urgent Pointer)字段配合使用。
已经发送了很长的一个程序要在远地的主机上运行。但后来发现了一些问题,需要取消该程序的运行,因此用户从键盘发出中断命令。如果不使用紧急数据,那么这两个字符将存储在接收TCP的缓存末尾。只有在所有的数据被处理完毕后这两个字符才被交付接收方的应用进程。这样做就浪费了很多时间。
# 确认ACK(ACKnowledgment)
仅当ACK = 1时确认号字段才有效,当ACK = 0时确认号无效。TCP规定,在连接建立后所有的传送的报文段都必须把ACK置为1。
确认标识,用于表示对数据包的成功接收。
# 推送 PSH(PuSH)
当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。这时,发送方TCP把PSH置为1,并立即创建一个报文段发送出去。接收方TCP收到PSH=1的报文段,就尽快地(即“推送”向前)交付接收应用进程。而不用再等到整个缓存都填满了后再向上交付。
推送标识,表示这个数据包应该被立即发送,不需要等待额外的数据
# 复位RST(ReSeT)
当RST=1时,表名TCP连接中出现了严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。RST置为1还用来拒绝一个非法的报文段或拒绝打开一个连接。
# 同步SYN(SYNchronization)
在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1,因此SYN置为1就表示这是一个连接请求或连接接受报文。
同步标识,表示TCP连接已初始化。
# 终止FIN(FINis,意思是“完”“终”)
完成标识,用来释放一个连接, 拆除上一个SYN标识。当FIN=1时,表明此报文段的发送发的数据已发送完毕,并要求释放运输连接。
一个完整的TCP连接过程一定会有SYN 和 FIN包。
# 窗口
占2字节。窗口值是【0,2^16-1】之间的整数。窗口指的是发送本报文段的一方的接受窗口(而不是自己的发送窗口)。窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量(以字节为单位)。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。总之,窗口值作为接收方让发送方设置其发送窗口的依据。
窗口字段明确指出了现在允许对方发送的数据量。窗口值经常在动态变化。
发送了一个报文段,其确认号是701,窗口字段是1000. 这就是告诉对方:“从701算起,我(即发送方报文段的一方)的接收缓存空间还可接受1000个字节数据(字节序号是701~1700),你在给我发数据时,必须考虑到这一点。”
# 检验和
占2字节。检验和字段检验的范围包括首部和数据这两部分。和UDP用户数据报一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。伪首部的格式和UDP用户数据报的伪首部一样。但应把伪首部第4个字段中的17改为6(TCP的协议号是6);把第5字段中的UDP中的长度改为TCP长度。接收方收到此报文段后,仍要加上这个伪首部来计算检验和。若使用TPv6, 则相应的伪首部也要改变。
# 紧急指针
占2字节。紧急指针仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据) 。因此,在紧急指针指出了紧急数据的末尾在报文段中的位置。当所有紧急数据都处理完时,TCP就告诉应用程序恢复到正常操作。值得注意的是,即使窗口为0时也可以发送紧急数据。
# 选项
长度可变,最长可达4字节。当没有使用“选项”时,TCP的首部长度是20字节。
- 最大报文段长度MSS(Maximum Segment Szie)。
最初规定的第一个选项。MSS是每一个TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个的TCP报文段。所以MSS并不是整个TCP报文段的最大长度,而是“TCP报文段长度减去TCP首部长度”。 MSS应尽可能大些,只要在IP层传输时不需要分片就行
- 窗口扩大选项是为了扩大窗口。
TCP首部中窗口字段长度是16位,因此最大的窗口大小为64K字节。虽然这对早期的网络是足够用的,但对于包含卫星信道的网络,传播时延和宽带都很大,要获得高吞吐量需要更大的窗口大小。 窗口扩大选项可以在双方初始建立TCP连接时进行协商。如果连接的某一端实现了窗口扩大,当它不再需要扩大其窗口时,可发送S=0选项,使窗口大小回到16。
- 时间戳选项
占10字节,其中最主要的字段是时间戳字段(4字节)和时间戳回送回答字段(4字节)。时间戳选项有以下两个概念:
(a). 用来计算往返时间RTT。 (b). 用于处理TCP序号超过2^32的情况,
# 三次握手
![三次握手](/img/browser/三次握手. gif)
# 过程
- 第一次握手:
由浏览器发起,告诉服务器我要发送请求了.
本机将标识位 **SYN **置为 1, seq = x(Sequence number)发送给服务端。此时本机状态为SYN-SENT.
- 第二次握手:
由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧.
服务器收到包之后,将状态切换为SYN-RECEIVED,并将标识位 SYN 和 ACK都置为1, seq = y, ack = x + 1, 并发送给客户端.
- 第三次握手:
由浏览器发送,告诉服务器,我马上就发了,准备接受吧.
客户端收到包后,将状态切换为ESTABLISHED,并将标识位ACK置为1,seq = x + 1, ack = y + 1, 并发送给服务端。服务端收到包之后,也将状态切换为ESTABLISHED.
# 为什么是三次不是两次,四次?
不能两次握手是为了防止已失效的连接请求报文段突然又传送到了服务端,造成服务端资源的浪费。 三次握手已经能说明握手时的通信是正常的,四次握手、五次握手就显得浪费了。
在一次TCP连接中,客户端A向服务端B发送连接请求SYN报文段,假如这个报文段没有及时被服务端B接收,而是滞留在网络的某处,于是客户端A超时重传,再次发送请求连接并且顺利与服务端B建立了连接,交换数据后断开连接。滞留在网络中的某处的陈旧报文就变成了失效的连接请求报文。
但如果这个失效的请求SYN报文段,现在又突然传送到了服务端B处,设想这时是使用两次握手而不是三次握手,服务端B就以为客户端A现在建立请求连接,于是服务端B发出确认,新的连接就建立了,服务端B分配资源,等待客户端A传送数据,但客户端A并没有想要建立TCP连接,不会理会服务端B发送的应答,也不会向服务端B传送数据,于是服务端B就白白等待,空耗资源。
使用三次握手可以避免这个情况。服务端B收到客户端A的失效的陈旧SYN报文段,向客户端A发送SYN报文段,选择自己的序号seq=y,确认收到客户端A的SYN报文段,确认号ack=x+1。第三次握手客户端A收到B的SYN报文段后,从确认号就可得知不应理睬这个SYN报文段(因为A现在并没有发送seq=x的报文段)。这时,客户端A会发送复位报文段,这个复位报文段中,RST=1,ACK=1,确认号ack=y+1。服务端B收到A的复位报文,就知道不建立TCP连接,不会分配资源等待A发送数据。
# 四次挥手
![四次挥手](/img/browser/四次挥手. gif)
# 过程
- 第一次挥手:
由浏览器发起的,发送给服务器,我请求报文发送完了,你准备关闭吧。
发起方向被动方发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态
- 第二次挥手:
由服务器发起的,告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧。
被动方发送报文,Ack、Seq,表示同意关闭请求。此时主机发起方进入 FIN_WAIT_2 状态
- 第三次挥手:
由服务器发起,告诉浏览器,我响应报文发送完了,你准备关闭吧。
被动方向发起方发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态
- 第四次挥手:
由浏览器发起,告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧。
发起方向被动方发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间未收到回复,则正常关闭。
# 为什么建立连接三次,关闭连接四次呢?
因为当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。
但是关闭连接时,当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了。所以只能先回复一个 ACK 报文,告诉 Client 端,"你发的FIN报文我收到了"。只有等到 Server 端所有的报文都发送完了,Client 才能发送 FIN 报文,因此不能一起发送。故需要四次挥手。
TCP 是全双工模式,接收到FIN时意味将没有数据再发来,但是还是可以继续发送数据。
# 为什么最后客户端还要等待 2*MSL的时间呢?
MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。
保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
# 拥塞控制
我们知道TCP通过一个定时器(timer)采样了RTT并计算RTO,但是,如果网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,然而重传会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这就导致了恶性循环,最终形成“网络风暴” —— TCP的拥塞控制机制就是用于应对这种情况。
# 介绍
产生原因:∑对资源的需求>可用资源
拥塞的标志:重传计时器超时;接收到三个重复确认
理想的传输条件:
- 传输信道不产生差错
- 不管发送方多快速度发送,接收方总来得及处理收到的数据
# 增加网络资源能解决问题吗
不能,网络拥塞是许多因素引起的,单纯的解决一个可能会使上述情况得到一些缓解,但是会把拥塞转移到其他地方。例如:把结点的存储空间扩大,更换更高速率的链路,提高结点处理机的运算速度,不仅不能解决问题,而且可能使网络性能更坏。
扩大结点存储空间——>由于输出链路的容量和处理机的速度并未提高,增大排队等待时间,超时重传,浪费资源。
更换更高速率的链路——>可能会缓解,也可能造成各部分不匹配。
TCP并不关心应用进程一次把多长的报文发送到TCP的缓存,而是根据窗口值网络拥塞成都决定 一个报文段应包含多少个字节
# 拥塞控制四算法
拥塞处理和流量控制不同,后者是作用于接收方,保证接收方来得及接受数据。而前者是作用于网络,防止过多的数据拥塞网络,避免出现网络负载过大的情况。
拥塞处理包括了四个算法,分别为:慢启动,拥塞避免,快重传,快恢复。
![拥塞控制](/img/browser/拥塞控制. png)
首先需要了解一个概念,为了在发送端调节所要发送的数据量,定义了一个“拥塞窗口”(Congestion Window),在发送数据时,将拥塞窗口的大小与接收端ack的窗口大小做比较,取较小者作为发送数据量的上限。
# 慢启动
cwnd的增长速度慢(指数增长),而是指TCP开始发送设置cwnd=1。刚刚加入网络的连接,一点一点地提速,不要一上来就把路占满。
![慢启动](/img/browser/慢启动. png)
- 连接建好的开始先初始化cwnd = 1,表明可以传一个MSS大小的数据。
- 每当收到一个ACK,cwnd++; 呈线性上升。
- 每当过了一个RTT,cwnd = cwnd*2; 呈指数让升
- 阈值ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”
# 拥塞避免(按线性规律增长)
当拥塞窗口 cwnd 达到一个阈值时,窗口大小不再呈指数上升,而是以线性上升,避免增长过快导致网络拥塞。让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞控制窗口加一。
![拥塞避免](/img/browser/拥塞避免. png)
- 每当收到一个ACK,cwnd = cwnd + 1/cwnd
- 每当过了一个RTT,cwnd = cwnd + 1
拥塞发生:当发生丢包进行数据包重传时,表示网络已经拥塞。分两种情况进行处理:
- 等到RTO超时,重传数据包,sshthresh = cwnd /2,cwnd 重置为 1。
- 在收到3个duplicate ACK时就开启重传,而不用等到RTO超时,sshthresh = cwnd = cwnd /2,进入快速恢复算法——Fast Recovery。
# 快重传
![快重传](/img/browser/快重传. png)
在收到3个duplicate ACK时就开启重传,而不用等到RTO超时。sshthresh = cwnd = cwnd /2,进入快速恢复算法——Fast Recovery
快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认. 快重传算法规定, 发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段, 而不必继续等待设置的重传计时器时间到期.
由于不需要等待设置的重传计时器到期, 能尽早重传未被确认的报文段, 能提高整个网络的吞吐量
# 快恢复
至少收到了3个Duplicated Acks,说明网络也不那么糟糕,可以快速恢复。
![快恢复](/img/browser/快恢复. png)
cwnd = sshthresh + 3 * MSS (3的意思是确认有3个数据包被收到了) 重传Duplicated ACKs指定的数据包 如果再收到 duplicated Acks,那么cwnd = cwnd +1 如果收到了新的Ack,那么,cwnd = sshthresh ,然后就进入了拥塞避免的算法了。
# TCP连接复用
TCP连接复用技术通过将前端多个客户的HTTP请求复用到后端与服务器建立的一个TCP连接上。这种技术能够大大减小服务器的性能负载,减少与服务器之间新建TCP连接所带来的延时,并最大限度的降低客户端对后端服务器的并发连接数请求,减少服务器的资源占用。
# 连接分类
# 长连接
一个tcp/ip连接上可以连续发送多个数据包,在tcp连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持(类似于心跳包),后续的读写操作会继续使用这个连接。
Client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,这样可以完全避免连累后端服务。
# 短连接
通信双方有数据交互时,就建立一个tcp连接,数据发送完成后,则断开此tcp连接。短连接一般只会在client/server间传递一次读写操作。
- 管理起来比较简单
- 存在的连接都是有用的连接
- 不需要额外的控制手段
- 但是消耗时间消耗资源
client向server发起连接请求,server接到请求,然后双方建立连接。client向server发送消息,server回应client,然后一次读写就完成了,这时候双方任何一个都可以发起close操作。
正常情况client先发起close操作?
一般情况下的server不会回复完client后立即关闭连接的,当然不排除有特殊的情况。
# 过程
# 一般情况下
- 客户端在发送HTTP请求之前需要先与服务器进行TCP三次握手,建立TCP连接,然后发送HTTP请求。
- 服务器收到HTTP请求后进行处理,并将处理的结果发送回客户端。
- 客户端和服务器互相发送FIN并在收到FIN的ACK确认后关闭连接。在这种方式下,一个简单的HTTP请求需要十几个TCP数据包才能处理完成。
# 采用TCP连接复用技术
- 客户端(如:ClientA)与负载均衡设备之间进行三次握手并发送HTTP请求。
- 负载均衡设备收到请求后,会检测服务器是否存在空闲的长连接,如果不存在,服务器将建立一个新连接。
- 当HTTP请求响应完成后,客户端则与负载均衡设备协商关闭连接,而负载均衡则保持与服务器之间的这个连接。
- 当有其它客户端(如:ClientB)需要发送HTTP请求时,负载均衡设备会直接向与服务器之间保持的这个空闲连接发送HTTP请求,避免了由于新建TCP连接造成的延时和服务器资源耗费。
# HTTP复用与TCP连接复用
在HTTP 1. 0中,客户端的每一个HTTP请求都必须通过独立的TCP连接进行处理。
在HTTP 1. 1中,对这种方式进行了改进。客户端可以在一个TCP连接中发送多个HTTP请求,这种技术叫做HTTP复用(HTTP Multiplexing)。
它与TCP连接复用最根本的区别在于,TCP连接复用是将多个客户端的HTTP请求复用到一个服务器端TCP连接上,而HTTP复用则是一个客户端的多个HTTP请求通过一个TCP连接进行处理。前者是负载均衡设备的独特功能;而后者是HTTP 1. 1协议所支持的新功能,目前被大多数浏览器所支持。
# 连接复用率决定TCP连接复用技术吗
TCP连接复用率:指一段时间内负载均衡设备成功处理的客户端HTTP请求总数与这段时间负载均衡与服务器之间建立的TCP连接总数的比值。不同的应用环境下计算出来的TCP连接复用率会有很大的差异,影响因素还有:
- 应用的特点
- 服务器设置
- 计算周期
- 请求的发送模式等
连接复用效率的关键在于负载均衡设备是否能够及时释放已经空闲的服务器端连接。有些厂商采用发送HTTP响应后等待一定时间,如果这段时间内无数据传输即释放该连接。而等待时间往往是秒级的,对于数据往返时间的毫秒级,其复用效果明显不会很好。
最为有效的连接复用技术是在负载均衡设备给客户端发送HTTP响应之后,收到客户端确认ACK数据包即释放该连接。这种方式避免了任何额外的等待时间,理论上没有更高效的复用方法。
# 使用
http1. 1下一个tcp连接虽然可以发多个请求, 这些请求是串行的, 有先后顺序。为了快, 还是会多创建tcp连接来并发。
http2允许一个域名6个TCP连接并发
头部 keep-alive保证创建是长连接
'Connection': 'close'
: tcp连接处理完一个请求就关闭,不使用长连接。
# UDP
UDP 协议是面向无连接的,也就是说不需要在正式传递数据之前先连接起双方。然后 UDP 协议只是数据报文的搬运工,不保证有序且不丢失的传递到对端,并且UDP 协议也没有任何控制流量的算法,总的来说 UDP 相较于 TCP 更加的轻便。
# 特点
# 面向无连接
UDP 是不需要和 TCP 一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了。 并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作
在发送端:应用层将数据传递给传输层的 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下是 UDP 协议,然后就传递给网络层了。
在接收端:网络层将数据传递给传输层,UDP 只去除 IP 报文头就传递给应用层,不会任何拼接操作
# 不可靠性
无连接
通信都不需要建立连接,想发就发。
不备份不关心
收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。
无拥塞控制
网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP
# 高效
UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的。
![udp首部](/img/browser/udp首部. png)
# 传输方式多
UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能。
# TCP与UDP区别
区别点 | TCP | UDP |
---|---|---|
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠 | 不可靠 |
速度 | 慢 | 快 |
传输方式 | 少 | 多 |