TCP 和 UDP 的区别

文章目录
前言
1. UDP
2. TCP
2.1 TCP 的三次握手
2.2 TCP 四次挥手
2.3 累计确认
2.4 顺序问题和丢包问题
2.5 流量控制的问题
2.6 拥塞控制的问题
总结及面试问题
前言
前端的面试中常常问的 TCP 和 UDP 的区别,网上也有好多内容,好比前端

TCP 和 UDP 的区别面试

TCP 是面向链接的,UDP 是面向无链接的
UDP程序结构较简单
TCP 是面向字节流的,UDP 是基于数据报的
TCP 保证数据正确性,UDP 可能丢包
TCP 保证数据顺序,UDP 不保证
以前也由于面试的缘由了解过一下,可是面试官又问了为何 TCP 是可靠传输,一下就露馅了,说不出来了,而后这两天就仔细了解了一下这方面的内容,还专门订阅了极客时间的趣谈网络协议,所以,这篇文章主要基于趣谈网络协议和本身的理解。算法

1. UDP
要想理解 TCP 和 UDP 的区别,首先要明白什么是 TCP,什么是 UDP缓存

TCP 和 UDP 是传输层的两个协议服务器

咱们来看一下 UDP 的包头网络

由上图能够看出,UDP 除了端口号,基本啥都没有了。若是没有这两个端口号,数据就不知道该发给哪一个应用。数据结构

因此 UDP 就像一个小孩子,特别简单,有以下三个特色tcp

UDP 的特色设计

沟通简单,不须要大量的数据结构,处理逻辑和包头字段
轻信他人。它不会创建链接,可是会监听这个地方,谁均可以传给它数据,它也能够传给任何人数据,甚至能够同时传给多我的数据。
愣头青,作事不懂变通。不会根据网络的状况进行拥塞控制,不管是否丢包,它该怎么发仍是怎么发
由于 UDP 是"小孩子",因此处理的是一些没那么难的项目,而且就算失败的也能接收。基于这些特色的话,UDP 可使用在以下场景中视频

UDP 的主要应用场景

须要资源少,网络状况稳定的内网,或者对于丢包不敏感的应用,好比 DHCP 就是基于 UDP 协议的。
不须要一对一沟通,创建链接,而是能够广播的应用。由于它不面向链接,因此能够作到一对多,承担广播或者多播的协议。
须要处理速度快,能够容忍丢包,可是即便网络拥塞,也绝不退缩,勇往直前的时候
基于 UDP 的几个例子

直播。直播对实时性的要求比较高,宁肯丢包,也不要卡顿的,因此不少直播应用都基于 UDP 实现了本身的视频传输协议
实时游戏。游戏的特色也是实时性比较高,在这种状况下,采用自定义的可靠的 UDP 协议,自定义重传策略,可以把产生的延迟降到最低,减小网络问题对游戏形成的影响
物联网。一方面,物联网领域中断资源少,极可能知识个很小的嵌入式系统,而维护 TCP 协议的代价太大了;另外一方面,物联网对实时性的要求也特别高。好比 Google 旗下的 Nest 简历 Thread Group,推出了物联网通讯协议 Thread,就是基于 UDP 协议的
还有一些,可是写的太多了也记不住,因此主要记住这几个就够了

2. TCP
首先是 TCP 的包头格式


TCP 的包头有哪些内容,分别有什么用

首先,源端口和目标端口是不可少的。
接下来是包的序号。主要是为了解决乱序问题。不编好号怎么知道哪一个先来,哪一个后到
确认序号。发出去的包应该有确认,这样能知道对方是否收到,若是没收到就应该从新发送,这个解决的是不丢包的问题
状态位。SYN 是发起一个连接,ACK 是回复,RST 是从新链接,FIN 是结束链接。由于 TCP 是面向链接的,所以须要双方维护链接的状态,这些状态位的包会引发双方的状态变动
窗口大小,TCP 要作流量控制,须要通讯双方各声明一个窗口,标识本身当前的处理能力。
经过对 TCP 头的解析,咱们知道要掌握 TCP 协议,应该重点关注如下问题:

顺序问题
丢包问题
链接维护
流量控制
拥塞控制
2.1 TCP 的三次握手
全部的问题,首先都要创建链接,因此首先是链接维护的问题

TCP 的创建链接称为三次握手,能够简单理解为下面这种状况

A:您好,我是 A
B:您好 A,我是 B
A:您好 B

至于为何是三次握手我这里就不细讲了,能够看其余人的博客,总结的话就是通讯双方全都有来有回

对于 A 来讲它发出请求,并收到了 B 的响应,对于 B 来讲它响应了 A 的请求,而且也接收到了响应。

TCP 的三次握手除了创建链接外,主要仍是为了沟通 TCP 包的序号问题。

A 告诉 B,我发起的包的序号是从哪一个号开始的,B 一样也告诉 A,B 发起的 包的序号是从哪一个号开始的。

双方创建链接以后须要共同维护一个状态机,在创建链接的过程当中,双方的状态变化时序图以下所示

这是网上常常见到的一张图,刚开始的时候,客户端和服务器都处于 CLOSED 状态,先是服务端主动监听某个端口,处于 LISTEN 状态。而后客户端主动发起链接 SYN,以后处于 SYN-SENT 状态。服务端接收了发起的链接,返回 SYN,而且 ACK ( 确认 ) 客户端的 SYN,以后处于 SYN-SENT 状态。客户端接收到服务端发送的 SYN 和 ACK 以后,发送 ACK 的 ACK,以后就处于 ESTAVLISHED 状态,由于它一发一收成功了。服务端收到 ACK 的 ACK 以后,也处于 ESTABLISHED 状态,由于它也一发一收了。

2.2 TCP 四次挥手
说完创建链接,再说下断开链接,也被称为四次挥手,能够简单理解以下

A:B 啊,我不想玩了
B:哦,你不想玩了啊,我知道了
这个时候,只是 A 不想玩了,即再也不发送数据,可是 B 可能还有未发送完的数据,因此须要等待 B 也主动关闭。
B:A 啊,好吧,我也不玩了,拜拜
A:好的,拜拜

这样整个链接就关闭了,固然上面只是正常的状态,也有些非正常的状态(好比 A 说完不玩了,直接跑路,B 发起的结束得不到 A 的回答,不知道该怎么办或则 B 直接跑路 A 不知道该怎么办),TCP 协议专门设计了几个状态来处理这些非正常状态

断开的时候,当 A 说不玩了,就进入 FIN_WAIT_1 的状态,B 收到 A 不玩了的消息后,进入 CLOSE_WAIT 的状态。

A 收到 B 说知道了,就进入 FIN_WAIT_2 的状态,若是 B 直接跑路,则 A 永远处与这个状态。TCP 协议里面并无对这个状态的处理,但 Linux 有,能够调整 tcp_fin_timeout 这个参数,设置一个超时时间。

若是 B 没有跑路,A 接收到 B 的不玩了请求以后,从 FIN_WAIT_2 状态结束,按说 A 能够跑路了,可是若是 B 没有接收到 A 跑路的 ACK 呢,就再也接收不到了,因此这时候 A 须要等待一段时间,由于若是 B 没接收到 A 的 ACK 的话会从新发送给 A,因此 A 的等待时间须要足够长。

2.3 累计确认
TCP 如何实现可靠传输?

首先为了保证顺序性,每一个包都有一个 ID。在创建链接的时候会商定起始 ID 是什么,而后按照 ID 一个个发送,为了保证不丢包,须要对发送的包都要进行应答,固然,这个应答不是一个一个来的,而是会应答某个以前的 ID,表示都收到了,这种模式成为累计应答或累计确认。

为了记录全部发送的包和接收的包,TCP 须要发送端和接收端分别来缓存这些记录,发送端的缓存里是按照包的 ID 一个个排列,根据处理的状况分红四个部分

发送而且确认的
发送还没有确认的
没有发送等待发送的
没有发送而且暂时不会发送的
这里的第三部分和第四部分就属于流量控制的内容

在 TCP 里,接收端会给发送端报一个窗口大小,叫 Advertised window。这个窗口应该等于上面的第二部分加上第三部分,超过这个窗口,接收端作不过来,就不能发送了

因而,发送端要保持下面的数据结构

对于接收端来说,它的缓存里面的内容要简单一些

接收而且确认过的
还没接收,可是立刻就能接收的
还没接收,但也没法接收的
对应的数据结构以下


2.4 顺序问题和丢包问题
结合上面的图看,在发送端,一、二、3 已发送并确认;四、五、六、七、八、9 都是发送了还没确认;十、十一、12 是还没发出的;1三、1四、15 是接收方没有空间,不许备发的。

在接收端来看,一、二、三、四、5 是已经完成 ACK 可是还没读取的;六、7 是等待接收的;八、9 是已经接收尚未 ACK 的。

发送端和接收端当前的状态以下:

一、二、3 没有问题,双方达成了一致
四、5 接收方说 ACK 了,可是发送方还没收到
六、七、八、9 确定都发了,可是 八、9 已经到了,六、7 没到,出现了乱序,缓存着可是没办法 ACK。
根据这个例子能够知道顺序问题和丢包问题都有可能存在,因此咱们先来看确认与重传机制。

假设 4 的确认收到了,5 的 ACK 丢了,六、7 的数据包丢了,该怎么办?

一种方法是超时重试,即对每个发送了可是没有 ACK 的包设定一个定时器,超过了必定的事件就从新尝试。这个时间必须大于往返时间,但也不宜过长,不然超时时间变长,访问就变慢了。

若是过一段时间,五、六、7 都超时了就会从新发送。接收方发现 5 原来接收过,因而丢弃 5;6 收到了,发送 ACK,要求下一个是 7,7 不幸又丢了。当 7 再次超时的时候,TCP 的策略是超时间隔加倍。每当遇到一次超时重传的时候,都会讲下一次超时时间间隔设为先前值的两倍。

超时重传的机制是超时周期可能相对较长,是否有更快的方式呢?

有一个快速重传的机制,即当接收方接收到一个序号大于指望的报文段时,就检测到了数据流之间的间隔,因而发送三个冗余的 ACK,客户端接收到以后,知道数据报丢失,因而重传丢失的报文段。

例如,接收方发现 六、八、9 都接收了,可是 7 没来,因此确定丢了,因而发送三个 6 的 ACK,要求下一个是 7。客户端接收到 3 个,就会发现 7 的确又丢了,不等超时,立刻重发。

2.5 流量控制的问题
在流量控制的机制里面,在对于包的确认中,会携带一个窗口的大小

简单的说一下就是接收端在发送 ACK 的时候会带上缓冲区的窗口大小,可是通常在窗口达到必定大小才会更新窗口,由于每次都更新的话,刚空下来就又被填满了

2.6 拥塞控制的问题
也是经过窗口的大小来控制的,可是检测网络满不尽是个挺难的事情,因此 TCP 发送包常常被比喻成往谁管理灌水,因此拥塞控制就是在不堵塞,不丢包的状况下尽量的发挥带宽。

水管有粗细,网络有带宽,即每秒钟能发送多少数据;水管有长度,端到端有时延。理想状态下,水管里面的水 = 水管粗细 * 水管长度。对于网络上,通道的容量 = 带宽 * 往返时延。

若是咱们设置发送窗口,使得发送但未确认的包为通道的容量,就能撑满整个管道。

如图所示,假设往返时间为 8 秒,去 4 秒,回 4 秒,每秒发送一个包,已通过去了 8 秒,则 8 个包都发出去了,其中前四个已经到达接收端,可是 ACK 还没返回,不能算发送成功,5-8 后四个包还在路上,还没被接收,这个时候,管道正好撑满,在发送端,已发送未确认的 8 个包,正好等于带宽,也即每秒发送一个包,也即每秒发送一个包,乘以来回时间 8 秒。

若是在这个基础上调大窗口,使得单位时间能够发送更多的包,那么会出现接收端处理不过来,多出来的包会被丢弃,这个时候,咱们能够增长一个缓存,可是缓存里面的包 4 秒内确定达不到接收端课,它的缺点会增长时延,若是时延达到必定程度就会超时重传

TCP 拥塞控制主要来避免两种现象,包丢失和超时重传,一旦出现了这些现象说明发送的太快了,要慢一点。

具体的方法就是发送端慢启动,好比倒水,刚开始倒的很慢,渐渐变快。而后设置一个阈值,当超过这个值的时候就要慢下来

慢下来仍是在增加,这时候就可能水满则溢,出现拥塞,须要下降倒水的速度,等水慢慢渗下去。

拥塞的一种表现是丢包,须要超时重传,这个时候,采用快速重传算法,将当前速度变为一半。因此速度仍是在比较高的值,也没有一晚上回到解放前。

总结及面试问题
TCP 和 UDP 的区别

TCP 是面向链接的,UDP 是面向无链接的
UDP程序结构较简单
TCP 是面向字节流的,UDP 是基于数据报的
TCP 保证数据正确性,UDP 可能丢包
TCP 保证数据顺序,UDP 不保证
什么是面向链接,什么是面向无链接

在互通以前,面向链接的协议会先创建链接,如 TCP 有三次握手,而 UDP 不会

TCP 为何是可靠链接

经过 TCP 链接传输的数据无差错,不丢失,不重复,且按顺序到达。TCP 报文头里面的序号能使 TCP 的数据按序到达报文头里面的确认序号能保证不丢包,累计确认及超时重传机制TCP 拥有流量控制及拥塞控制的机制

相关文章
相关标签/搜索