网络面试-0x12 UDP和TCP的区别以及应用场景

Posted 谷_寒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络面试-0x12 UDP和TCP的区别以及应用场景相关的知识,希望对你有一定的参考价值。

一、 UDP (user datagram protocol)用户数据报协议

①: 一种简单的面向数据报的通讯协议,即:应用层传下来的报文,不合并,不拆分,只是在其上面加上首部后就交给了下面的网络层。无论应用层交给UDP多长的报文,它统统发送,一次发送一个报文。
②: 接收方,接到后直接去除首部,交给上面的应用层就完成任务
③:UDP报头包含4个字段,每个字段占用2个字节,标题段,开销小

特点: 1)UDP不提供复杂的控制机制,利用IP提供面向无连接的通讯服务 —— 连接
2)传输途中出现丢包, UDP也不负责重发 —— 丢包不处理
3)当报的到达顺序出现乱序时,UDP没有纠正的能力 —— 无纠正能力
4)接收方接收到数据的那一刻,立即按照原样发送到网络上的一种机制。即使是出现网络拥堵的情况,UDP 也无法进行流量控制等避免网络拥塞的行为。 —— 网络拥塞无法处理

1、UDP为什么不可靠? bind和connect对于UDP的作用是什么?

UDP 只有一个socket接受缓冲区,没有socket发送缓存区。 即为:只要有数据就发,不管对方是否可以正确接收。而在对方的 socket 接收缓冲区满了之后,新来的数据报无法进入到 socket 接受缓冲区,此数据报就会被丢弃,因此 UDP 不能保证数据能够到达目的地,此外,UDP 也没有流量控制和重传机制,故UDP的数据传输是不可靠的。

connect: 和 TCP 建立连接时采用三次握手不同,UDP 中调用 connect 只是把对端的 IP 和 端口号记录下来,并且 UDP 可多多次调用 connect 来指定一个新的 IP 和端口号,或者断开旧的 IP 和端口号(通过设置 connect 函数的第二个参数)。和普通的 UDP 相比,调用 connect 的 UDP 会提升效率,并且在高并发服务中会增加系统稳定性

bind: 当 UDP 的发送端调用 bind 函数时,就会将这个套接字指定一个端口,若不调用 bind 函数,系统内核会随机分配一个端口给该套接字。当手动绑定时,能够避免内核来执行这一操作,从而在一定程度上提高性能。

二、 TCP (Transmissioin Control Protocl)传输控制协议

①:一种可靠、面向字节流的通讯协议,把上面应用层交下来的数据看成无结构的字节流来发送。
②:可以想象成为流水形式,发送方TCP 会将数据放入“蓄水池”(缓存区),等到可以发送的时候发送,不能发送就等着。
③:TCP会根据网络的拥塞状态来确定每个报文段的大小。
④:报文首部有20个字节,额外开销大。

TCP结构 源端口和目的端口:它用于多路复用/分解来自或送往上层应用的数据,其和IP数据报中的源IP与目的IP地址一同确定一条TCP连接。
序号和确认号字段:序号是本报文段发送的数据部分中第一个字节的编号,在 TCP 传送的流中,每一个字节一个序号。例如一个报文段的序号为 100,此报文段数据部分共有 100 个字节,则下一个报文段的序号为 200。序号确保了 TCP 传输的有序性。确认号,即 ACK,指明下一个想要收到的字节序号,发送 ACK 时表明当前序号之前的所有数据已经正确接收。这两个字段的主要目的是保证数据可靠传输。
首部长度:该字段指示了以 32 比特的字为单位的 TCP 的首部长度。其中固定字段长度为 20 字节,由于首部长度可能含有可选项内容,因此 TCP 报头的长度是不确定的,20 字节是 TCP 首部的最小长度。
保留:为将来用于新的用途而保留。
控制位

URG 表示紧急指针标志,该位为 1 时表示紧急指针有效,为 0 则忽略;
ACK 为确认序号标志,即相应报文段包括一个对已被成功接收报文段的确认;
PSH 为 push 标志,当该位为 1 时,则指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队;
RST 为重置连接标志,当出现错误连接时,使用此标志来拒绝非法的请求;
SYN 为同步序号,在连接的建立过程中使用,例如三次握手时,发送方发送 SYN 包表示请求建立连接;
FIN 为 finish 标志,用于释放连接,为 1 时表示发送方已经没有数据发送了,即关闭本方数据流。

接收窗口:主要用于 TCP 流量控制。该字段用来告诉发送方其窗口(缓冲区)大小,以此控制发送速率,从而达到流量控制的目的。
校验和:奇偶校验,此校验和是对整个 TCP 报文段,包括 TCP 头部和 数据部分。该校验和是一个端到端的校验和,由发送端计算和存储,并由接收端进行验证,主要目的是检验数据是否发生改动,若检测出差错,接收方会丢弃该 TCP 报文。
紧急数据指针:紧急数据用于告知紧急数据所在的位置,在URG标志位为 1 时才有效。当紧急数据存在时,TCP 必须通知接收方的上层实体,接收方会对紧急模式采取相应的处理。
选项:该字段一般为空,可根据首部长度进行推算。主要有以下作用:

① TCP 连接初始化时,通信双方确认最大报文长度。
② 在高速数据传输时,可使用该选项协商窗口扩大因子。
③ 作为时间戳时,提供一个 较为精准的 RTT。

数据:TCP 报文中的数据部分也是可选的,例如在 TCP 三次握手和四次挥手过程中,通信双方交换的报文只包含头部信息,数据部分为空,只有当连接成功建立后,TCP 包才真正携带数据。

特点: 1)TCP充分地实现了数据传输时各种控制功能,可以进行丢包时重发控制,还可以对次序乱掉的分包进行顺序控制,而这些在UDP中都没有 —— 丢包处理、纠正处理
2)TCP是面向连接的协议,只有确认通讯对端存在时才会发送数据,从而可以控制通信流量的浪费 —— 可避免拥塞的控制
3)根据TCP这些机制,IPO这种无连接的网络上也能够实现高可靠性的通讯(主要通过:校验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现)—— 基于无连接的IP进行高可靠的协议的需要处理的

1、TCP的定[计]时器

TCP有 7 中计时器:

  1. 建立连接定时器:该定时器是在建立TCP连接的时候使用的,在TCP三次握手的过程中,发送方发送SYN时,会启动一个定时器(默认为3秒),若SYN包丢失了,那么3秒以后会重新发送SYN包直到达到重传的次数。
  2. 重传定时器:该计时器主要用于TCP超时重传机制中, 当TCP发送报文段时,就会创建特定报文的重传计时器,并可能出现两种情况:

①:若在计时器截止之前发送方收到的ACK报文,则撤销该计时器。
②:若计时器截止时间内并没有收到接收方的ACK报文,则发送方重传报文,并将计时器复位。

  1. 坚持计时器:TCP通过让接收方指明希望从发送方接受的数据字节数(窗口大小)来进行流量控制,当接收端的接收窗口满时,接收端会告诉发送端此时窗口已满,请停止发送数据。此时,发送端和接收端的窗口大小均为0,直到窗口变为非0时,接收端将发送一个确认ACK告诉发送端可以再次发送数据,但是该报文有可能在传输时丢失。若该ACK报文丢失,则双方可能会一直等待下去,为了避免这种死锁情况,发送方使用一个坚持定时器来周期性的向结合搜发发送探测报文段,以查看接受方窗口是否变大。 —— 发送方和接收方窗口都是0,若是接收方窗口变成了非0,发送一个ack给发送端,但是丢失了,从而产生了客户端轮询的定时器 ——> 坚持计时器
  2. 延迟应答计时器:【又称捎带ACK】, 在延迟应答的时候使用的。 为了提高网络传输的效率,当服务器接收到客户端的数据后,不是立即回ACK给客户端,而是等一段时间,这样如果服务端有数据需要发送给客户端的话,就可以把数据和ACK一起发送给客户端了。
  3. 保活定时器:该定时器是在建立 TCP 连接时指定 SO_KEEPLIVE 时才会生效,当发送方和接收方长时间没有进行数据交互时,该定时器可以用于确定对端是否还活着。
  4. FIN_WAIT_2定时器:主动请求关闭的一方发送FIN报文给接收端并且收到其对FIN的确认ACK后进入FIN_WAIT_2状态。如果这个时候因为网络突然断掉、被动关闭的一端宕机等原因,到时请求方没有收到接收方发来的FIN,主动关闭的一方回一直等待。—— 该定时器的作用就是为了避免这种情况的发生。当该定时器超时的时候,请求关闭比方将不再等待,直接释放连接。
  5. TIME_WAIT定时器:TCP四次挥手中,发送方在最后一次挥手之后回进入TIME_WAIT状态,不直接进入CLOSE状态的主要原因是被动关闭方玩意在超时时间内没有收到最后一个ACK,则还会重发最后的FIN。 —— (1)2MSL等待时间保证了重发的FIN会被主动关闭的一端收到且重新发送以后一个ACK。(2)在这2MSL的时间段内任何迟到的报文段会被接受方丢弃,从而防止老的TCP连接的包在新的TCP连接里面出现。
2、TCP如何保证可靠性的?
  1. 数据分块: 应用数据被分割成TCP认为最适合发送的数据块
  2. 序列号和确认应答:TCP给发送的每个包进行编号,在传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答,即发送ACK报文,这个ACK报文当中带有对应的确认序列号,刚告诉发送方成功接收了哪些数据以及下一次的数据从哪里开始发。除次之外,接收方可以根据序列号对数据进行排序,把有序数据传送给应用层,并丢弃重复的数据。
  3. 校验和:TCP将保持它首部和数据部分的校验和,目的是检测数据在传输过程中的任何变化。 如果收到报文段的校验和也有差错,TCP将丢弃这个报文段并且不确认收到的此报文
  4. 流量控制:TCP连接的双方都一个固定大小的缓冲空间,发送方发送的数据量不能够超过接收端缓冲区的大小,当接收方来不及处理发送方的数据,会提示发送方降低发送的速率,防止产生丢包。TCP通过滑动窗口协议来支持流量控制机制。
  5. 拥塞控制:当网络某个节点发生拥塞时,减少数据的发送
  6. ARQ协议:也是为了实现可靠传输的,它的基本原理就是每发完一个分组就定制发送,等待对方确认。 在收到确认后,再发下一个分组。
  7. 超时重传:当TCP发出一个报文段后,它启动一个定时器,等待目的段确认收到这个报文段,如果超过某个时间还没有收到确认,将重发这个报文段。
3、TCP超时重传原理?

发送方在发送一次数据后就开启一个定时器,在一定时间内如果没有得到发送数据包的 ACK 报文,那么就重新发送数据,在达到一定次数还没有成功的话就放弃重传并发送一个复位信号。其中超时时间的计算是超时的核心,而定时时间的确定往往需要进行适当的权衡,因为当定时时间过长会造成网络利用率不高,定时太短会造成多次重传,使得网络阻塞。在 TCP 连接过程中,会参考当前的网络状况从而找到一个合适的超时时间。

4、TCP的停止等待协议是什么?

停止等待协议是为了实现 TCP 可靠传输而提出的一种相对简单的协议,该协议指的是发送方每发完一组数据后,直到收到接收方的确认信号才继续发送下一组数据。【在已发送但未确认的报文被确认之前, 发送方的滑动窗口将不会滑动】

四种情形:理解停等协议是人如何实现可靠传输的:

无差错传输 :A 发送分组 Msg 1,发完就暂停发送,直到收到接收方确认收到 Msg 1 的报文后,继续发送 Msg 2,以此类推,该情形是通信中的一种理想状态。
出现差错发:送方发送的报文出现差错导致接收方不能正确接收数据,出现差错的情况主要分为两种:

<1> 发送方发送的 Msg 1 在中途丢失了,接收方完全没收到数据。
<2> 接收方收到 Msg 1 后检测出现了差错,直接丢弃 Msg 1。
上面两种情况,接收方都不会回任何消息给发送方,此时就会触发超时传输机制,即发送方在等待一段时间后仍然没有收到接收方的确认,就认为刚才发送的数据丢失了,因此重传前面发送过的数据。

确认丢失 当接收方回应的 Msg 1 确认报文在传输过程中丢失,发送方无法接收到确认报文。于是发送方等待一段时间后重传 Msg 1,接收方将收到重复的 Msg1 数据包,此时接收方会丢弃掉这个重复报文并向发送方再次发送 Msg1 的确认报文。

确认迟到 当接收方回应的 Msg 1 确认报文由于网络各种原因导致发送方没有及时收到,此时发送方在超时重传机制的作用下再次发送了 Msg 数据包,接收方此时进行和确认丢失情形下相同的动作(丢弃重复的数据包并再次发送 Msg 1 确认报文)。发送方此时收到了接收方的确认数据包,于是继续进行数据发送。过了一段时间后,发送方收到了迟到的 Msg 1 确认包会直接丢弃。

5、TCP最大的连接数限制?

Client 最大 TCP 连接数 client 在每次发起 TCP 连接请求时,如果自己并不指定端口的话,系统会随机选择一个本地端口(local port),该端口是独占的,不能和其他 TCP 连接共享。TCP 端口的数据类型是 unsigned short,因此本地端口个数最大只有 65536,除了端口 0不能使用外,其他端口在空闲时都可以正常使用,这样可用端口最多有 65535 个。

Server最大 TCP 连接数 server 通常固定在某个本地端口上监听,等待 client 的连接请求。不考虑地址重用(Unix 的 SO_REUSEADDR 选项)的情况下,即使 server 端有多个 IP,本地监听端口也是独占的,因此 server 端 TCP 连接 4 元组中只有客户端的 IP 地址和端口号是可变的,因此最大 TCP 连接为客户端 IP 数 × 客户端 port 数,对 IPV4,在不考虑 IP 地址分类的情况下,最大 TCP 连接数约为 2 的 32 次方(IP 数)× 2 的 16 次方(port 数),也就是 server 端单机最大 TCP 连接数约为 2 的 48 次方。

然而上面给出的是只是理论上的单机最大连接数,在实际环境中,受到明文规定(一些 IP 地址和端口具有特殊含义,没有对外开放)、机器资源、操作系统等的限制,特别是 sever 端,其最大并发 TCP 连接数远不能达到理论上限。对 server 端,通过增加内存、修改最大文件描述符个数等参数,单机最大并发 TCP 连接数超过 10 万 是没问题的。

6、TCP流量控制与拥塞控制

流量控制
所谓流量控制就是让发送方的发送速率不要太快,让接收方来得及接收。如果接收方来不及接收发送方发送的数据,那么就会有分组丢失。在 TCP 中利用可变长的滑动窗口机制可以很方便的在 TCP 连接上实现对发送方的流量控制。主要的方式是接收方返回的 ACK 中会包含自己的接收窗口大小,以控制发送方此次发送的数据量大小(发送窗口大小)。

拥塞控制
在实际的网络通信系统中,除了发送方和接收方外,还有路由器,交换机等复杂的网络传输线路,此时就需要拥塞控制。拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况。常用的解决方法有:慢开始和拥塞避免、快重传和快恢复

拥塞控制和流量控制的区别

  1. 拥塞控制往往是一种全局的,防止过多的数据注入到网络之中,而TCP连接的端点只要不能收到对方的确认信息,猜想在网络中发生了拥塞,但并不知道发生在何处
  2. 流量控制往往指点对点通信量的控制,是端到端的问题。

困惑:滑动窗口和拥塞窗口的不明确:
滑动窗口(协议):是传输层将进行流量控制的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快二人导致自己被淹没的目的。 —— 滑动窗口可以理解为协议、机制、或者服务器滑动窗口大小。 ——> 主要的是:接收方还可以接收的大小通告发送方控制发送的大小。

拥塞窗口【congestion window 简称:cwnd】:可以看做是发送端用来进行流量(拥塞)控制的窗口。拥塞是指一个或者多个交换点的数据报超载而导致时延剧烈增加的现象。为了控制拥塞,TCP使用了第二个窗口限制,即拥塞窗口限制。对于拥塞窗口大小的限制采用慢开始和乘法减小两种技术。
乘法减小的拥塞避免策略:一旦发现报文段丢失,就把拥塞窗口的大小减半(直到减至最小的窗口,窗口中应至少包含一个报文段)。
慢开始恢复:拥塞窗口随着一个确认的到达,拥塞窗口的大小每次增加一个报文段。

拥塞窗口是发送方使用的流量控制,而通告/滑动窗口则是接收方使用的流量控制。

7、如果接收方滑动窗口满了,发送方会怎么做?

基于 TCP 流量控制中的滑动窗口协议,我们知道接收方返回给发送方的 ACK 包中会包含自己的接收窗口大小,若接收窗口已满,此时接收方返回给发送方的接收窗口大小为 0,此时发送方会等待接收方发送的窗口大小直到变为非 0 为止,然而,接收方回应的 ACK 包是存在丢失的可能的,为了防止双方一直等待而出现死锁情况,此时就需要坚持计时器来辅助发送方周期性地向接收方查询,以便发现窗口是否变大【坚持计时器参考问题】,当发现窗口大小变为非零时,发送方便继续发送数据。

8、拥塞控制采用的四种算法

ssthresh: ss阈值
cwnd: Congestion Window 拥塞窗口
rwnd:Receiver Window 接收者窗口 —— 即为:滑动窗口 Sliding window

慢开始的乘以2的原因
网络拥塞 —— 即为超时
快重传示意图,cwnd这个时候应该是不变的
快恢复
  1. 慢开始(慢启动) —— 传数据从1快速增加 当发送方开始发送数据时,由于一开始不知道网络负荷情况,如果立即将大量的数据字节传输到网络中,那么就有可能引起网络拥塞。一个较好的方法是在一开始发送少量的数据先探测一下网络状况,即由小到大的增大发送窗口(拥塞窗口 cwnd)。慢开始的慢指的是初始时令 cwnd为 1,即一开始发送一个报文段。如果收到确认,则 cwnd = 2,之后每收到一个确认报文,就令 cwnd = cwnd* 2。
    但是,为了防止拥塞窗口增长过大而引起网络拥塞,另外设置了一个慢开始门限 ssthresh。
    ① 当 cwnd < ssthresh 时,使用上述的慢开始算法;
    ② 当 cwnd > ssthresh 时,停止使用慢开始,转而使用拥塞避免算法

  2. 拥塞避免 —— 传数量慢慢增加 拥塞控制是为了让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT (往返时间定义为发送方发送数据到收到确认报文所经历的时间)就把发送方的 cwnd 值加 1,通过让 cwnd 线性增长,防止很快就遇到网络拥塞状态。
    当网络拥塞发生时,让新的慢开始门限值变为发生拥塞时候的值的一半,并将拥塞窗口置为 1 ,然后再次重复两种算法(慢开始和拥塞避免),这时一瞬间会将网络中的数据量大量降低。

  3. 快重传 —— 传输缺失的数据 快重传算法要求接收方每收到一个失序的报文就立即发送重复确认,而不要等到自己发送数据时才捎带进行确认,假定发送方发送了 Msg 1 ~ Msg 4 这 4 个报文,已知接收方收到了 Msg 1,Msg 3 和 Msg 4 报文,此时因为接收到收到了失序的数据包,按照快重传的约定,接收方应立即向发送方发送 Msg 1 的重复确认。 于是在接收方收到 Msg 4 报文的时候,向发送方发送的仍然是 Msg 1 的重复确认。这样,发送方就收到了 3 次 Msg 1 的重复确认,于是立即重传对方未收到的 Msg 报文。由于发送方尽早重传未被确认的报文段,因此,快重传算法可以提高网络的吞吐量。

  4. 快恢复 快恢复算法是和快重传算法配合使用的,该算法主要有以下两个要点:

① 当发送方连续收到三个重复确认,执行乘法减小,慢开始门限 ssthresh 值减半;

② 由于发送方可能认为网络现在没有拥塞,因此与慢开始不同,把 cwnd 值设置为 ssthresh 减半之后的值,然后执行拥塞避免算法,线性增大 cwnd。

小结: 1)滑动窗口和拥塞窗口大小比较,取小的值。
2) 上面讨论的慢启动和拥塞避免算法都是在 拥塞窗口<滑动窗口的情况下。 否则,就直接使用滑动窗口了。
3) 主要就是:慢启动、拥塞避免、快恢复
4) 判断是使用快恢复/拥塞避免还是慢启动+拥塞避免,要看拥塞当前是超时了,还是快恢复?如果我收到了多次的同一个序列号的ack,那就是快恢复,如果是超时了,那就是拥塞避免。

滑动串口和拥塞窗口的合作:

  1. 发送端主机在确认发送报文段的速率时,既要根据接收端的接收能力,又要从全局考虑不要使网络发生拥塞
  2. 因此,每个tcp连接需要也有以下两个状态变量: a:接收端窗口 b:拥塞窗口
  3. 收端窗口:是接收端根据其一目前的接收缓存大小所许诺的最新窗口值,时来自接收端的流量控制。接收端将此值放在TCP报文的首部中的窗口字段,传给发送端
  4. 拥塞窗口:是发送端根据自己估计的网络拥塞程度而设置的窗口值,是来自发送端的流量控制
  5. 发送端的发送窗口的上限值取自接收端窗口和拥塞窗口两这种较小的一个。

参考: https://blog.csdn.net/weixin_41501074/article/details/110941340

9、TCP粘包问题

为什么会发生TCP粘包和拆包?
① 发送方写入的数据大于套接字缓冲区的大小,此时将发生拆包。
② 发送方写入的数据小于套接字缓冲区大小,由于 TCP 默认使用 Nagle 算法,只有当收到一个确认后,才将分组发送给对端,当发送方收集了多个较小的分组,就会一起发送给对端,这将会发生粘包。
③ 进行 MSS (最大报文长度)大小的 TCP 分段,当 TCP 报文的数据部分大于 MSS 的时候将发生拆包。
④ 发送方发送的数据太快,接收方处理数据的速度赶不上发送端的速度,将发生粘包。

常见解决方法
① 在消息的头部添加消息长度字段,服务端获取消息头的时候解析消息长度,然后向后读取相应长度的内容。
② 固定消息数据的长度,服务端每次读取既定长度的内容作为一条完整消息,当消息不够长时,空位补上固定字符。但是该方法会浪费网络资源。
③ 设置消息边界,也可以理解为分隔符,服务端从数据流中按消息边界分离出消息内容,一般使用换行符。

什么时候需要处理粘包问题? 当接收端同时收到多个分组,并且这些分组之间毫无关系时,需要处理粘包;而当多个分组属于同一数据

计算机网络测试人关于TCP的学习和梳理

通过阅读《计算机网络–自顶向下方法》,以及结合最近面试的一些经历,作此笔记进行梳理和总结,也为日后的回顾作基底。


1)什么是TCP?

1.1 TCP与运输层

运输层(Transport Layer)位于应用层和网络层之间,该层协议为运行在不同主机上的应用进程之间提供了逻辑通信功能。

  • 即应用进程使用运输层提供的逻辑通信功能彼此发送报文,而无须考虑承载这些报文的物理基础设施的细节。
  • 运输层和网络层的关系:运输层位于网络层之上,网络层提供主机之间的逻辑通信服务,运输层为运行在不同主机上的进程之间提供逻辑通信服务。
  • 关于网络层级架构具体介绍可移步《【计算机网络】OSI与TCP/IP网络架构》

运输层协议在端系统中实现:

  • 在发送端:将来自发送应用进程的应用报文分块,每块加上一个运输层首部以生成运输层报文段(segment),然后传递给网络层。
  • 在接收端:处理接收到的报文段,将其中的数据供接收应用进程使用。

*面试常问之TCP和HTTP的联系和区别

联系:

区别:

  • HTTP属于应用层协议,定义了传输数据内容的规范。

  • TCP属于运输层协议,定义了数据传输和连接方式的规范。

  • HTTP算是短连接,TCP算是长连接。

因特网有两种协议(TCP和UDP),可为调用的应用程序提供一组不同的传输层服务。

  • UDP(用户数据报协):为调用它的应用程序提供了一种不可靠的、无连接的服务。
  • TCP(传输控制协议):为调用它的应用程序提供了一种可靠的、面向连接的服务。

TCP和UDP最基本的责任是将两个端系统间IP的交付服务扩展成运行在端系统上的两个进程之间的交付服务,即运输层的多路复用和多路分解:

  • 多路分解:将运输层报文段中的数据交付到正确的套接字。
  • 多路复用:从不同套接字中收集数据块、为其封装首部信息以生成报文段、将报文段传递给网络层。
    • 要求:套接字有唯一标识符(源端口号字段)、报文段有特殊字段指示目的套接字(目的端口号字段)。
      • 端口号(0 - 65535)
      • 周知端口号(0 - 1023),在[RFC1700]给出,在[RFC3232]更新。

网络层协议(IP,网际协议)为主机之间提供逻辑通信,其服务模型是尽力而为交付服务(best-effort delivery
service)。

  • 因为其不确保报文段的交付,不保证报文段的按序交付,不保证报文段中的数据的完整性,因此也被称为不可靠服务(unreliable service)

1.2 TCP与UDP

  • 无连接运输:UDP

    • 工作原理:给从应用进程得到的数据添加源和目的端口号字段,以及两个其他的小字段(长度和校验和),然后交给网络层,反之则将IP报文段的数据根据目的端口号交付给正确的应用进程。
    • 适用场景
      • 实时应用(通常要求最小的发送速率,不过分延迟,可容忍部分数据丢失)
      • 特定服务(无连接因此可支持更多的活跃客户,以及更快)
      • 如DNS、SNMP、网络电话、实时视频会议、流式存储音频与视频

  • 面向连接的运输:TCP

    • 工作原理
      • 面向连接:通过三次握手建立连接,四次挥手断开连接。
      • 通过差错检测、重传、累积确认、定时器、序号和确认号来保证可靠传输。
      • TCP定义在RFC793、RFC1122、RFC1323、RFC2018、RFC2581中。
    • 常用场景:如SMTP、Telnet等。

  • UDP与TCP的区别:

    • 无连接与有连接
    • TCP要求系统资源较多,UDP较少
    • UDP程序结构较简单
    • TCP保证数据正确性,UDP可能丢包
    • TCP保证数据顺序,UDP不保证
    • 详细的区别可参考:https://blog.csdn.net/Li_Ning_/article/details/52117463


2)面试常问之TCP如何实现可靠传输?

TCP服务模型是一个字节流,TCP必须检测并修补所有在IP层(及下面的层)产生的数据传输问题,如丢包、重复以及错误。

2.1 连接管理

一个TCP连接通常分为3个阶段:启动、数据传输、退出(关闭)。

  • 一个TCP连接由一对端点或套接字构成,通信的每一端都由一对(IP地址、端口号)所唯一标识。
  • 连接建立过程(三次握手):

    三次握手的目的不仅在于让通信双方了解一个连接正在建立,而且还利用SYN报文段交换彼此的初始序列号(ISN)。
    在这里插入图片描述
    1. 客户端发送一个SYN报文段,并指明自己想要连接的端口号和初始序列号x(表明传送数据时的第一个数据字节的序号是 x)。
    2. 服务器发送响应SYN报文段,包含其初始序列号y,此外确认号ack=x+1(若出现丢失的情况,该SYN段会被重传)。
    3. 客户端为了确认服务器的SYN,发送确认号ack=y+1的报文。

*面试常问之为什么是三次握手而不是两次?

为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。

  • 详细原因:如果在发送过程中的话,假如是两次:
    • 当A给B发送一个连接请求,因为网络的原因该请求没有按时到达,A就会重新发送一次请求,这次请求正常到,然后B就会给A一个确认请求,此时就可以传送数据了。
    • 但是当A第一次发送的数据又来到了(A以为这个包已经丢失了),那么B就会再次向A发送一个确认,此时的A就不知道这个确认的意义了,而B就会在一直等待着A给他发送信息(如果这样的次数很多就会导致资源浪费)。
    • 所以不能是两次。

  • 连接关闭过程(四次挥手):

    通过发送一个FIN报文段来发起关闭操作,由于TCP的通信模型是双向的,所以只有连接双方都完成关闭操作后,才构成一个完整关闭。
    在这里插入图片描述
    1. 连接的主动关闭者发送一个FIN段,进入FIN_WAIT_1。
    2. 被动关闭者发送的报文段中确认号ack=u+1,以表明其已经成功收到主动关闭者的FIN。此时,上层应用程序会被告知连接的另一端已经提出了关闭的请求。
    3. 若此时没有要发送的数据时,应用程序会发起自己的关闭操作,接着被动关闭者的身份转变为主动关闭者,并发送自己的FIN。
    4. 收到连接释放报文段后,为了完成连接的关闭,还会发送一个ACK用于确认上一个FIN。注意,当出现FIN丢失的情况,发送方会重新传输直到收到一个ACK确认。

*面试常问之为什么是四次挥手而不是三次?

因为TCP连接是全双工的,也就是说接收到FIN只是说没有数据再发过来,但是还是可以向对方发送数据的,也就是说接受到一个FIN只是关闭了一个方向的数据传输,另一个方向还可以继续发送数据

  • 前两次挥手只是确认关闭了一个方向的数据,加上后面两次挥手才真正的关闭了整个全双工连接。

  • 当socket在ESTABISHED状态时,它想主动关闭连接于是向对方发送FIN请求,发送完FIN请求后它处于FIN_WAIT_1状态,当对方确认ACK报文后则处于FIN_WAIT_2状态。

    • FIN_WAIT_2表示半连接,也就是有一方要求关闭连接,另一方收到请求但是告诉它我还有一些数据要发送稍后会关闭。
    • TIME_WAIT状态表示收到对方的FIN并发送出ACK

如果是三次挥手,则可能在关闭后还有一个方向没有关

*面试常问之2MSL:

客户端接收到服务器端的 FIN 报文后进入TIME_WAIT状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:

  • 确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
  • 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文

2.2 校验和

发送的数据包的二进制相加然后取反,目的是检测数据在传输过程中的任何变化。

  • 如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。

2.3 序列号和ACK信号

发送方按照顺序给要发送的数据包的每个字节都标上编号。
接收方接收到发送方的数据包之后,回传一个ACK信号,标识下一个需求的数据包初始字节编号。

  • 序列号
    • TCP提供一个字节流接口,把一个应用程序的字节流转换为一组IP可以携带的分组,这些分组包含序列号。
    • 序列号在TCP中实际代表了每个分组的第一个字节在整个数据流中的字节偏移。
    • 通过序列号的使用,一个TCP接收端可丢弃重复的报文段和记录以乱序到达的报文段。

  • ACK信号
    • 当TCP接收到另一端的数据时,会发送一个确认。
    • TCP使用的ACK是累积的,一个指示字节号N的ACK表示了所有直到N的字节(但不包括N)已经成功被接收了。

2.4 超时重传

发送方没有接收到响应的ACK报文原因可能有两点:

  • 数据在传输过程中由于网络原因等直接全体丢包,接收方没有接收到。
  • 接收方接收到了响应的数据,但是发送的ACK报文响应却由于网络原因丢包了。

TCP在解决这个问题的时候引入了一个新的机制,叫做超时重传机制。

发送方在发送完数据后等待一个时间,该时间内没有接收到ACK报文,那么就会重新发送刚才的数据。

  • 如果是上述第一个原因,则接收方收到二次重发的数据后,便进行ACK应答。
  • 如果是第二个原因,接收方发现接收的数据已存在(判断存在的根据就是序列号,所以说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送ACK应答。
  • 等待时间的设定:
    • 为了保证在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。
      • 超时以500ms(0.5秒)为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。
      • 重发一次后,仍未响应,那么等待2500ms的时间后,再次重传。等待4500ms的时间继续重传。以一个指数的形式增长。
    • 累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。

2.5 滑动窗口

TCP必需要解决的可靠传输以及包乱序(reordering)的问题,所以,TCP必需要知道网络实际的数据处理带宽或是数据处理速度,这样才不会引起网络拥塞,导致丢包。

  • 发送方滑动窗口示意图:
    在这里插入图片描述
    分成了四个部分,分别是(其中那个黑模型就是滑动窗口):

    1. 已收到ack确认的数据。
    2. 已发出但还没收到ack的。
    3. 在窗口中还没有发出的(接收方还有空间)。
    4. 窗口以外的数据(接收方没空间)。

  • 下面是个滑动后的示意图(收到36的ack,并发出了46-51的字节):
    在这里插入图片描述

滑动窗口中窗口前段为已发送但为收到ACK的数据,后段为待发送数据。

  • 发送端一次发送多个数据,接收端回传收到的连续数据的ACK信号,缓存缺失数据之后的数据包(保持顺序)。
  • 当发送端收到ACK信号时,窗口向前依次移动,直到遇到有数据未确认时停止。
  • 一段时间后启动超时重传,接收端若收到缺失数据,则和缓存数据一起发送ACK信号,否则,抛弃缓存数据。

2.6 流量控制

接收端在接收到数据后,对其进行处理。

  • 如果发送端的发送速度太快,导致接收端的结束缓冲区很快的填充满了。此时如果发送端仍旧发送数据,那么接下来发送的数据都会丢包,继而导致丢包的一系列连锁反应,如超时重传。

而TCP根据接收端对数据的处理能力,决定发送端的发送速度,这个机制就是流量控制。

简单来说就是接收方处理不过来的时候,就把窗口缩小,并把窗口值告诉发送端。

  • TCP首部有一个字段来通知窗口的大小,接收端通过设置来主动控制传输流量。
  • 如果接收到窗口大小的值为0,那么发送方将停止发送数据,并定期的向接收端发送窗口探测数据段,让接收端把窗口大小告诉发送端。

2.7 拥塞控制

  • 如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。
    • 这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度
  • 发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口

发送端通过拥塞窗口主动控制传输流量。主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。

在这里插入图片描述

  • 慢开始:防止双方通信刚开始就传送大量数据包,发送端拥塞窗口初始设置为1MSS(以报文段而非字节为单位),每接受一个ACK信号,窗口扩大为两倍。

    • 发送数据时,取拥塞窗口和滑动窗口的较小值。同时设定一个慢启动阈值,初始值设置为16个报文段,即ssthresh=16。

  • 拥塞避免

    • 一开始以慢开始算法(指数增长)。当cwnd=16时开始执行拥塞避免算法,呈现线性增长。
    • 当拥塞窗口cwnd=24时出现超时,发送方判定为网络拥塞,于是调整门限值ssthresh=cwnd/2=12,同时设置拥塞窗口为1,进入慢开始阶段。
    • 按照慢开始算法,发送方每收到一个新报文段的确认ACK拥塞窗口值增加。当cwnd=12时(图中点3)执行拥塞避免算法。

TCP以段为单位发送数据包:在建立TCP连接的同时,两端协商发送数据包的单位,称为“最大消息长度”:MSS。

  • 【TCP数据(MSS字节)】【TCP首部(20字节)】【IP首部(20字节)】
  • 快重传和快恢复
    • 当cwnd=16时(图中点4)出现了一个新的情况,就是发送方连续收到3个对统一报文段的重复确认(3-ACK)。发送方执行快重传和快恢复算法。
      • 在图中点4,发送方知道只是丢失了个别的报文段,于是不启动慢开始,而是先进行快重传然后执行快恢复算法。
      • 发送方设置调整门限值ssthresh=cwnd/2=8, 同时拥塞窗口cwnd=ssthresh=8(点5),然后进行拥塞避免算法。
    • 快重传:收到3个同样的确认就立刻重传特定的报文,不等到超时。
    • 快恢复:cwnd不是从1重新开始。


【部分内容参考自】

  • 《计算机网络–自顶向下方法》
  • 《TCP/IP详解 卷1:协议》
  • TCP的三次握手和四次挥手:https://www.cnblogs.com/xiaokang01/p/10032377.html
  • TCP实现可靠传输:https://www.cnblogs.com/walker993/p/9570902.html
  • TCP协议如何保证可靠传输:https://www.cnblogs.com/xiaokang01/p/10033267.html

以上是关于网络面试-0x12 UDP和TCP的区别以及应用场景的主要内容,如果未能解决你的问题,请参考以下文章

前端面试题-TCP和UDP的区别

java后台面试之计算机网络问题集锦

[Java网络安全系列面试题] 说一说TCP和UDP的区别与联系?

网络笔试面试题整理

「 计算机网络 」说说TCP和UDP的区别及其应用场景

阿里面试官:TCP和UDP的区别?