计算机网络常见面试题总结

计算机网络常见面试题总结2---传输层

TCP数据包结构

在这里插入图片描述

  • 源端口和目的端口 :各占2个字节,分别标识源主机的应用进程和目的主机的应用进程,唯一确定一条TCP连接;
  • 序号seq :占4个字节,标识从源端向目的端发送的数据字节流,表示这个报文段中的第一个数据字节的顺序号。TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;
  • 确认号ack :占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;只有下面的ACK置为1时,此字段才有效。
  • 数据偏移 :占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远;
  • 紧急 URG :当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
  • 确认 ACK :当 ACK=1 时确认号字段有效,否则无效。TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置 1。
  • 推送 PSH :当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,而不用等待缓冲区装满。这时候就将PSH=1;
  • 复位 RST :当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
  • 同步 SYN :在连接建立时用来同步序号。当 SYN=1,ACK=0 时表示这是一个连接请求报文段。若对方同意建立连接,则响应报文中 SYN=1,ACK=1。
  • 终止 FIN :用来释放一个连接,当 FIN=1 时,表示此报文段的发送方的数据已发送完毕,并要求释放连接。
  • 窗口 :占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;
  • 检验和 :占2字节,校验首部和数据这两部分;
  • 紧急指针 :占2字节,指出本报文段中的紧急数据的字节数;
  • 选项 :长度可变,定义一些其他的可选的参数,如最长报文大小。

TCP连接建立:三次握手

为了准确无误地把数据送达目标处,TCP协议采用了三次握手策略。这种建立连接的方式可以防止错误
的连接,TCP使用的流量控制协议是可变大小的滑动窗口。

三次握手过程

在这里插入图片描述
在握手之前,主动打开连接的客户端结束 CLOSE 阶段,被动打开的服务器也结束 CLOSE 阶段,并进入 LISTEN (监听)阶段。随后进入三次握手阶段:

1、首先客户端向服务器发送一个 SYN 包,并等待服务器确认,其中:

标志位为 SYN = 1,表示请求建立连接;
序号为 Seq = x(x 一般取随机数);
随后客户端进入 SYN-SENT (同步已发送)阶段。
TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。

2、服务器接收到客户端发来的 SYN 包后,对该包进行确认后结束 LISTEN 阶段,表示同意连接,并返回一段 TCP 报文,其中:

标志位为 SYN = 1 和 ACK = 1,表示确认客户端的报文 Seq 序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接;
序号为 Seq = y;
确认号为 Ack = x + 1,表示收到客户端的序号 Seq 并将其值加 1 作为自己确认号 Ack 的值,随后服务器端进入 SYN-RECV(同步收到) 阶段。
这个报文也不能携带数据,但是同样要消耗一个序号。

3、客户端接收到发送的 SYN + ACK 包后,明确了从客户端到服务器的数据传输是正常的,从而结束 SYN-SENT 阶段。并返回最后一段报文。其中:

标志位为 ACK = 1,表示确认收到服务器端同意连接的信号;
序号为 Seq = x + 1,表示收到服务器端的确认号 Ack,并将其值作为自己的序号值;
确认号为 Ack= y + 1,表示收到服务器端序号 seq,并将其值加 1 作为自己的确认号 Ack 的值。
随后客户端进入 ESTABLISHED。
当服务器端收到来自客户端确认收到服务器数据的报文后,得知从服务器到客户端的数据传输是正常的,从而结束 SYN-RECV 阶段,进入 ESTABLISHED (已建立连接)阶段,从而完成三次握手。

为什么需要三次握手?

三次握手的目的是建立可靠的通信信道,即双方确认自己与对方的发送与接收是正常的。其中通信简单来说就是数据的发送与接收。

第一次握手:Client什么都不能确认;Server确认了对方发送正常,自己接收正常;
第二次握手:Client确认了:自己发送、接收正常,对方发送、接收正常;Server确认了:对方发送正常,自己接收正常
第三次握手:Client确认了:自己发送、接收正常,对方发送、接收正常;Server确认了:自己发送、接收正常,对方发送、接收正常。
所以三次握手就能确认双发收发功能都正常,缺一不可。

若采用两次握手,当第二次握手后就建立连接的话,此时客户端知道服务器能够正常接收到自己发送的数据,而服务器并不知道客户端是否能够收到自己发送的数据。
如果没有第三次握手告诉服务器客户端能否收到服务器传输的数据的话,服务器端的端口就会一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。长此以往,这样的端口越来越多,就会造成服务器开销的浪费。

如果两次握手会有什么问题?

A发送消息给B,这个消息由于网络的原因,阻塞在某个节点了,如下图:
在这里插入图片描述
如果阻塞的时间很长,超出了设定的超时重发时间,那么A就会认为这个消息丢失了,然后重新发送。当A和B通信完成后,这个之前被A认为“丢失的消息”到达了B,而对于B而言,以为这是一个新的请求连接消息,就向A发了一次确认。而对于A而言,认为自己没有给B再次的发消息(因为上次的通话已经结束了)。所以A不会理睬这条确认,但是B则会一直等待A的消息。这就导致了B的时间被白白浪费(对于服务器而言,就是CPU等资源的一种浪费),这样是万万不可的,这就是为什么不能两次握手的原因。

四次握手会怎样?

如果四次就造成了浪费,因为在三次结束之后,就已经可以保证A可以给B发信息,A可以收到B的信息;B可以给A发信息,B可以收到A的信息。

如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

为什么要传回 SYN?

接收端传回发送端所发送的 SYN 是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。

传了 SYN,为啥还要传 ACK?

  • 双方通信无误必须是两者互相发送信息都无误。传了 SYN,证明发送方到接收方的通道没有问题,但是接收方到发送方的通道还需要 ACK 信号来进行验证。
  • 防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误(避免两次握手可能会出现的问题的情况出现)。 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

第三次握手失败

server端就会启动超时重传机制,超过规定时间后重新发送SYN+ACK,重传次数默认是5次。如果重传指定次数到了后,仍然未收到ACK应答,那么一段时间后,server自动关闭这个连接。但是client认为这个连接已经建立,如果client端向server写数据,server端将以RST包响应。

RST

重置连接、复位连接,用来关闭异常的连接。
发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区中的包,发送RST。
而接收端收到RST包后,也不必发送ACK包来确认。
什么时候发送RST:

  • 端口未打开;
  • 请求超时;
  • 提前关闭;
  • 在一个已关闭的socket上收到数据。

如果三次握手的时候每次握手信息对方没有收到会怎么样?

若第一次握手服务器未收到客户端请求建立连接的数据包时,服务器不会进行任何相应的动作,而客户端由于在一段时间内没有收到服务器发来的确认报文,因此会等待一段时间后重新发送SYN同步报文,若仍然没有回应,则重复上述过程直到发送次数超过最大重传次数限制后,建立连接的系统调用会返回-1。

若第二次握手客户端未接收到服务器回应的 ACK 报文时,客户端会采取第一次握手失败时的动作,这里不再重复,而服务器端此时将阻塞在 accept() 系统调用处等待 client 再次发送 ACK 报文。

若第三次握手服务器未接收到客户端发送过来的 ACK 报文,同样会采取类似于客户端的超时重传机制,若重传次数超过限制后仍然没有回应,则 accep() 系统调用返回 -1,服务器端连接建立失败。但此时客户端认为自己已经连接成功了,因此开始向服务器端发送数据,但是服务器端的 accept() 系统调用已返回,此时没有在监听状态。因此服务器端接收到来自客户端发送来的数据时会发送 RST 报文给 客户端,消除客户端单方面建立连接的状态。

洪泛攻击

攻击者发送TCP SYN,而当服务器返回ACK后,该攻击者就不对其进行再确认,那这个TCP连接就处于挂起状态,服务器收不到再确认的话,还会重复发送ACK给攻击者。这样更加会浪费服务器的资源。攻击者就对服务器发送非常大量的这种TCP连接,由于每一个都没法完成三次握手,所以在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法为正常用户提供服务了。

解决方案:

  • 降低重传次数/重传时间。
  • 采用类似cookie的设置,同一IP多次请求连接不回应 则将其丢弃。

TCP连接释放:四次挥手

四次挥手过程

断开一个 TCP 连接则需要四次挥手,由于TCP的半关闭性(全双工,每个方向单独关闭)。

在这里插入图片描述
四次挥手即 TCP 连接的释放,这里假设客户端主动释放连接。在挥手之前主动释放连接的客户端结束 ESTABLISHED 阶段,随后开始四次挥手:

1、首先客户端向服务器发送一段 TCP 报文表明其想要释放 TCP 连接,其中:

标记位为 FIN = 1,表示请求释放连接;
序号为 Seq = u(等于前面已经传送过来的数据的最后一个字节的序号加1);
随后客户端进入 FIN-WAIT-1 (终止等待1)阶段,即半关闭阶段,并且停止向服务端发送通信数据。

2、服务器接收到客户端请求断开连接的FIN报文后,结束ESTABLISHED 阶段,进入 CLOSE-WAIT(关闭等待) 阶段并返回一段 TCP 报文,其中:

标记位为 ACK = 1,表示接收到客户端释放连接的请求;
序号为 Seq = v;
确认号为 Ack = u + 1,表示是在收到客户端报文的基础上,将其序号值加 1 作为本段报文确认号 Ack 的值;
随后服务器开始准备释放服务器端到客户端方向上的连接。这时候处于半关闭状态,即客户端已经没有数据要发送,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
客户端收到服务器发送过来的 TCP 报文后,确认服务器已经收到了客户端连接释放的请求,随后客户端结束 FIN-WAIT-1 阶段,进入 FIN-WAIT-2 (终止等待2)阶段,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

3、服务器端在发出 ACK 确认报文后,服务器端会将遗留的待传数据传送给客户端,待传输完成后即经过 CLOSE-WAIT 阶段,便做好了释放服务器端到客户端的连接准备,再次向客户端发出一段 TCP 报文,其中:

标记位为 FIN = 1 和 ACK = 1,表示已经准备好释放连接了;
序号为 Seq = w;
确认号 Ack = u + 1,表示是在收到客户端报文的基础上,将其序号 Seq 的值加 1 作为本段报文确认号 Ack 的值。
随后服务器端结束 CLOSE-WAIT 阶段,进入 LAST-ACK (最后确认)阶段。并且停止向客户端发送数据。

4、客户端收到从服务器发来的 TCP 报文,确认了服务器已经做好释放连接的准备,于是结束 FIN-WAIT-2 阶段,进入 TIME-WAIT (时间等待)阶段,并向服务器发送一段报文,其中:

标记位为 ACK = 1,表示接收到服务器准备好释放连接的信号;
序号为 Seq= u + 1,表示是在已收到服务器报文的基础上,将其确认号 Ack 值作为本段序号的值;
确认号为 Ack= w + 1,表示是在收到了服务器报文的基础上,将其序号 Seq 的值作为本段报文确认号的值。
随后客户端开始在 TIME-WAIT 阶段等待 2 MSL。服务器端收到从客户端发出的 TCP 报文之后结束 LAST-ACK 阶段,进入 CLOSED 阶段。由此正式确认关闭服务器端到客户端方向上的连接。客户端等待完 2 MSL 之后,结束 TIME-WAIT 阶段,进入 CLOSED 阶段,由此完成四次挥手。

服务器结束TCP连接的时间要比客户端早一些。

为什么是四次挥手?

第一次挥手:client告诉server自己的数据已全部发送,client可以回收发送缓冲区,server可以回收接收缓冲区;
第二次挥手:server告诉client自己收到了关闭信息;
第三次挥手:server告诉client自己的数据已全部发送,server可以回收发送缓冲区,client可以回收接收缓冲区;
第四次挥手:client告诉server自己收到了关闭信息。
TCP是全双工通信,服务端和客户端都能发送和接收数据。所以TCP在断开连接时,需要服务端和客户端都确定对方不再发送数据。任何一方都可以在数据传输结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后完全关闭TCP连接。
在客户端第1次挥手后,服务端可能还在发送数据,所以第2次挥手和第3次挥手不能合并。

CLOSE-WAIT的意义

在服务器收到客户端关闭连接的请求并告诉客户端自己已经成功收到了该请求之后,服务器进入了 CLOSE-WAIT 状态,然而此时有可能服务端还有一些数据没有传输完成,因此不能立即关闭连接,而 CLOSE-WAIT 状态就是为了保证服务器在关闭连接之前将待发送的数据发送完成。

TIME-WAIT 的意义

TIME-WAIT 就是TCP释放连接的四次挥手后的主动关闭连接方的等待状态。

  • 可靠地实现TCP全双工连接的终止。为了保证A发送的最后一个ACK报文能够到达B。
  • 允许旧的报文段在网络中消逝。TCP不允许处于TIME_WAIT状态的连接启动一个新的连接。因为TIME_WAIT状态持续2MSL(MSL,最大分段生存期,TCP报文在 Internet 上最长生存时间)就可以保证当再次成功建立一个TCP连接时,来自之前连接的旧的报文段已经在网络中消逝,不会再出现在新的连接中。
  • 假设客户端最后一次发送的 ACK 包在传输的时候丢失了,由于 TCP 协议的超时重传机制,服务端将重发 FIN 报文,若客户端并没有维持 TIME-WAIT 状态而直接关闭的话,当收到服务端重新发送的 FIN 包时,客户端就会用 RST 包来响应服务端,这将会使得对方认为是有错误发生,然而其实只是正常的关闭连接过程,并没有出现异常情况。

为什么设定时间为2MSL?

2 MSL 即是服务器端发出 FIN 报文和客户端发出的 ACK 确认报文所能保持有效的最大时长。

  • 为了保证客户端发送的最后一个ACK报文段能够到达服务器。

若服务器在 1 MSL 内没有收到客户端发出的 ACK 确认报文,再次向客户端发出 FIN 报文。如果客户端在 2 MSL 内收到了服务器再次发来的 FIN 报文,说明服务器由于一些原因并没有收到客户端发出的 ACK 确认报文。客户端将再次向服务器发出 ACK 确认报文,并重新开始 2 MSL 的计时。
若客户端在 2MSL 内没有再次收到服务器发送的 FIN 报文,则说明服务器正常接收到客户端 ACK 确认报文,客户端可以进入 CLOSE 阶段,即完成四次挥手。
所以客户端要经历 2 MSL 时长的 TIME-WAIT 阶段,为的是确认服务器能否接收到客户端发出的 ACK 确认报文。

  • 在第四次挥手后,经过2MSL的时间足以让本次连接产生的所有报文段都从网络中消失,这样下一次新的连接中就肯定不会出现旧连接的报文段了。

TIME_WAIT 状态会导致什么问题,怎么解决?

考虑高并发短连接的业务场景,在高并发短连接的 TCP 服务器上,当服务器处理完请求后主动请求关闭连接,这样服务器上会有大量的连接处于 TIME_WAIT 状态,服务器维护每一个连接需要一个 socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些正常的 连接失败。
解决方案:修改配置或设置 SO_REUSEADDR 套接字,使得服务器处于 TIME-WAIT 状态下的端口能够快速回收和重用。

有很多 TIME-WAIT 状态如何解决?

服务器可以设置 SO_REUSEADDR 套接字选项来通知内核,如果端口被占用,但 TCP 连接位于 TIME_WAIT 状态时可以重用端口。如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时 SO_REUSEADDR 选项就可以避免 TIME-WAIT 状态。
也可以采用长连接的方式减少 TCP 的连接与断开,在长连接的业务中往往不需要考虑 TIME-WAIT 状态,但其实在长连接的业务中并发量一般不会太高。

有很多 CLOSE-WAIT 怎么解决?

首先检查是不是自己的代码问题(看是否服务端程序忘记关闭连接),如果是,则修改代码。
调整系统参数,包括句柄相关参数和 TCP/IP 的参数,一般一个 CLOSE_WAIT 会维持至少 2 个小时的时间,我们可以通过调整参数来缩短这个时间。

TCP 如何保证可靠传输?

  • 数据分块:应用数据被分割成 TCP 认为最适合发送的数据块。
  • 序列号和确认应答:TCP 给发送的每一个包进行编号,在传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答,即发送 ACK 报文,这个 ACK 报文当中带有对应的确认序列号,告诉发送方成功接收了哪些数据以及下一次的数据从哪里开始发。除此之外,接收方可以根据序列号对数据包进行排序,把有序数据传送给应用层,并丢弃重复的数据。
  • 校验和:TCP 将保持它首部和数据部分的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到报文段的检验和有差错,TCP 将丢弃这个报文段并且不确认收到此报文段。
  • 流量控制:TCP 连接的双方都有一个固定大小的缓冲空间,发送方发送的数据量不能超过接收端缓冲区的大小。当接收方来不及处理发送方的数据,会提示发送方降低发送的速率,防止产生丢包。TCP 通过滑动窗口协议来支持流量控制机制。
  • 拥塞控制:当网络某个节点发生拥塞时,减少数据的发送。
  • ARQ协议:自动重传请求。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。ARQ包括 停止等待ARQ协议 和 连续ARQ协议,拥有错误检测、正面确认、超时重传和 负面确认及重传等机制。
  • 超时重传:当TCP发出一个报文段后,它启动一个定时器,等待目的端确认收到这个报文段。如果超过某个时间还没有收到确认,将重发这个报文段。

流量控制

所谓流量控制就是让发送方的发送速率不要太快,让接收方来得及接收。在 TCP 中利用可变长的滑动窗口机制可以很方便的在 TCP 连接上实现对发送方的流量控制。

接收方每次收到数据包,在发送确认报文时,同时告诉发送方自己的缓存区剩余空间,我们也把缓存区的剩余大小称之为接收窗口大小,用变量win来表示接收窗口的大小。发送方收到之后,便会调整自己的发送速率,当发送方收到接收窗口的大小为0时,发送方就会停止发送数据。当发送方收到接受窗口 win = 0 时,这时发送方停止发送报文,并且同时开启一个定时器,每隔一段时间就发个测试报文去询问接收方,打听是否可以继续发送数据了,如果可以,接收方就告诉他此时接受窗口的大小;如果接受窗口大小还是为0,则发送方再次刷新启动定时器。

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

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

拥塞控制

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

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

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

停止等待ARQ协议

停止等待协议是为了实现 TCP 可靠传输而提出的一种相对简单的协议,该协议指的是发送方每发完一组数据后,直到收到接收方的确认信号才继续发送下一组数据。通过四种情形来帮助理解停等协议是如何实现可靠传输的:
在这里插入图片描述

  • 无差错传输

如上述左图所示,A 发送分组 Msg 1,发完就暂停发送,直到收到接收方确认收到 Msg 1 的报文后,继续发送 Msg 2,以此类推,该情形是通信中的一种理想状态。

  • 出现差错

如上述右图所示,发送方发送的报文出现差错导致接收方不能正确接收数据,出现差错的情况主要分为两种:
发送方发送的 Msg 1 在中途丢失了,接收方完全没收到数据。
接收方收到 Msg 1 后检测出现了差错,直接丢弃 Msg 1。
上面两种情形,接收方都不会回任何消息给发送方,此时就会触发超时传输机制,即发送方在等待一段时间后仍然没有收到接收方的确认,就认为刚才发送的数据丢失了,因此重传前面发送过的数据。因此每发送完一个分组需要设置一个超时计时器,其重传时间应比数据在分组传输的平均往返时间更长一些。
在这里插入图片描述

  • 确认丢失

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

  • 确认迟到

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

特点:简单;信道利用率低,等待时间长。

连续ARQ协议

由于停止等待ARQ协议信道利用率太低,所以需要使用连续ARQ协议来进行改善。连续 ARQ 协议可提高信道利用率。
在这里插入图片描述
图(a)是发送方维持的发送窗口,它的意义是:位于发送窗口内的5个分组都可以连续发送出去,而不需要等待对方的确认,这样就提高了信道利用率。

连续ARQ协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。例如上面的图(b),当发送方收到第一个分组的确认,就把发送窗口向前移动一个分组的位置。如果原来已经发送了前5个分组,则现在可以发送窗口内的第6个分组。

接收方一般都是采用累积确认的方式。也就是说接收方不必对收到的分组逐个发送确认。而是在收到几个分组后,对按序到达的最后一个分组发送确认。如果收到了这个分组确认信息,则表示到这个分组为止的所有分组都已经正确接收到了。

累积确认的优点是容易实现,即使确认丢失也不必重传。但缺点是,不能正确的向发送方反映出接收方已经正确收到的所以分组的信息。比如发送方发送了前5个分组,而中间的第3个分组丢失了,这时候接收方只能对前2个发出确认。而不知道后面3个分组的下落,因此只能把后面的3个分组都重传一次,这种机制叫Go-back-N(回退N),表示需要再退回来重传已发送过的N个分组。

TCP 超时重传的原理

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

TCP 拥塞控制采用的四种算法

拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

四种算法:慢开始和拥塞避免、快重传和快恢复。
在这里插入图片描述

慢开始

当发送方开始发送数据时,由于一开始不知道网络负荷情况,如果立即将大量的数据字节传输到网络中,那么就有可能引起网络拥塞。一个较好的方法是在一开始发送少量的数据先探测一下网络状况,即由小到大的增大发送窗口(拥塞窗口 cwnd)。慢开始的慢指的是初始时令 cwnd为 1,即一开始发送一个报文段。如果收到确认,则 cwnd = 2,之后每收到一个确认报文,就令 cwnd = cwnd* 2。
但是,为了防止拥塞窗口增长过大而引起网络拥塞,另外设置了一个慢开始门限 ssthresh。

  • 当 cwnd < ssthresh 时,使用上述的慢开始算法;
  • 当 cwnd > ssthresh 时,停止使用慢开始,转而使用拥塞避免算法;
  • 当 cwnd == ssthresh 时,两者均可。

指数增长阶段

拥塞避免

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

线性增长阶段

快重传

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

快恢复

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

  • 当发送方连续收到三个重复确认,执行乘法减小,慢开始门限 ssthresh 值减半;
  • 由于发送方可能认为网络现在没有拥塞,因此与慢开始不同,把 cwnd 值设置为 ssthresh 减半之后的值,然后执行拥塞避免算法,线性增大 cwnd。

TCP的各种机制

慢启动机制

最初的TCP的实现方式是,在连接建立成功后便会向网络中发送大尺寸的数据包,假如网络出现问题,很多这样的数据包会积攒在路由器上,很容易导致网络中路由器缓存空间耗尽,从而发生拥塞。
现在的TCP协议规定了,新建立的连接不能一开始就发送大尺寸的数据包,而只能从一个小尺寸的数据包开始发送,在发送和数据被对方确认的过程中去计算对方的接收速度,来逐步增加每次发送的数据量(最后到达一个稳定的值,进入高速传输阶段。相应的,慢启动过程中TCP通道处在低速传输阶段),以避免上述现象的发生。这个策略就是慢启动。

保活机制

TCP保活机制是一种在不影响数据流内容的情况下探测对方的方式。它由一个保活计时器实现,当计时器被激发,连接一端将发送一个保活探测(简称保活)报文,另一端接收报文的同时会发送一个ACK作为响应。
开启该功能的一端会发现对方处于以下四种状态之一:

  • 对方主机仍在工作,并且可以到达。
  • 对方主机已经崩溃,包括已经关闭或者正在重新启动。
  • 客户主机崩溃并且已重启。
  • 对方主机仍在工作,但是由于某些原因不能到达请求端。

优点:可以判断对方是否还在线。因为对于非正常断开的TCP连接,系统并不能侦测到(比如网线断掉)。可以判断连接是否中断。长时间没有任何数据发送,连接可能会被中断。因为网络连接中间可能会经过路由器、防火墙等设备,而这些有可能会使长时间没有活动的连接断掉。
缺点:在出现短暂的网络错误的时候,保活机制会使一个好的连接断开;且保活机制会占用不必要的带宽。

确认应答(ACK)机制

对每一个发送的数据段,都要给一个ACK确认应答,收到ACK后再发送下一个数据段。TCP将每个字节的数据都进行了编号,即为序列号。每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据,下一次你从哪里开始发。这样做有一个较大的缺点,就是性能较差,尤其是数据往返时间较长的情况下。

超时重传机制

主机A发送数据给B以后,可能因为网络拥堵等原因,数据无法到达主机B。如果主机A在一个特定时间间隔(500ms的指数倍,动态计算)内没有收到B发来的确认应答,就会进行重发。但是,主机A未收到主机B发来的确认应答,也可能是因为ACK丢失了。因此主机B会收到很多重复数据,那么TCP协议需要能够识别出哪些包是重复的包,并且将这些重复的包丢弃掉,这时我们就可以利用前面提到的序列号,就可以很容易做到去重的效果。

滑动窗口机制

既然一收一发的方式性能较低,那么我们可以一次发送多条数据,这样就可以大大的提高性能。这样做的本质其实就是将多个段的等待时间重叠在一起了。

窗口大小指的是无需等待确认应答而可以继续发送的数据的最大值,这个最大值由接收方的接收缓冲区大小决定。现假设窗口大小为4000个字节(4个段),那么发送前四个段时,不需要等待任何ACK,直接发送。收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据,依次类推。

操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据才能从缓冲区删掉。窗口越大,则网络的吞吐率就越高。

TCP 粘包问题

为什么会发生TCP粘包和拆包?

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

常见解决方法

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

什么时候需要处理粘包问题?

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

为什么UDP协议不存在“粘包问题”?

对于UDP,若还没有上层交付数据,UDP的报文长度仍然在。同时,UDP是一个一个将数据交付给应用层的,具有很明显的数据边界;
站在应用层的角度,使用UDP时,要么收到完整的UDP报文,要么不收,不会出现“半个”的情况。

什么是TCP半连接队列和全连接队列?

在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:半连接队列(SYN 队列)和全连接队列(accept 队列)

服务端收到客户端发起的 SYN 请求后,内核会把该连接存储到SYN队列,并向客户端响应 SYN+ACK,之后服务端进入SYN_RCVD状态。接着客户端会返回 ACK,服务端收到第三次握手的 ACK 后,内核会把连接从SYN队列移除,然后创建新的全连接,并将其添加到 accept 队列,等待进程调用 accept 函数时把连接取出来。

半连接队列:大小由/proc/sys/net/ipv4/tcp_max_syn_backlog控制,Linux的默认是1024。当服务端发送SYN_ACK后将会开启一个定时器,如果超时没有收到客户端的ACK,将会重发SYN_ACK包。重传的次数由/proc/sys/net/ipv4/tcp_synack_retries控制,默认是5次。
全连接队列:大小通过/proc/sys/net/core/somaxconn指定,在使用listen函数时,内核会根据传入的backlog参数与系统参数somaxconn,取二者的较小值。

TCP 协议中的定时器

TCP中有七种计时器,分别为:

  • 建立连接定时器:顾名思义,该定时器在建立TCP连接时使用,在TCP 三次握手的过程中,发送方发送 SYN 时,会启动一个定时器(默认为 3 秒),若 SYN 包丢失了,那么 3 秒以后会重新发送 SYN 包,直到达到重传次数。
  • 重传定时器:该计时器主要用于 TCP 超时重传机制中,当TCP 发送报文段时,就会创建特定报文的重传计时器,并可能出现两种情况:
    1、若在计时器截止之前发送方收到了接收方的 ACK 报文,则撤销该计时器;
    2、若计时器截止时间内并没有收到接收方的 ACK 报文,则发送方重传报文,并将计时器复位。
  • 坚持计时器:我们知道 TCP 通过让接受方指明希望从发送方接收的数据字节数(窗口大小)来进行流量控制,当接收端的接收窗口满时,接收端会告诉发送端此时窗口已满,请停止发送数据。此时发送端和接收端的窗口大小均为0,直到窗口变为非0时,接收端将发送一个 确认 ACK 告诉发送端可以再次发送数据,但是该报文有可能在传输时丢失。若该 ACK 报文丢失,则双方可能会一直等待下去,为了避免这种死锁情况的发生,发送方使用一个坚持定时器来周期性地向接收方发送探测报文段,以查看接收方窗口是否变大。
  • 延迟应答计时器:延迟应答也被称为捎带 ACK,这个定时器是在延迟应答的时候使用的,为了提高网络传输的效率,当服务器接收到客户端的数据后,不是立即回 ACK 给客户端,而是等一段时间,这样如果服务端有数据需要发送给客户端的话,就可以把数据和 ACK 一起发送给客户端了。
  • 保活定时器:该定时器是在建立 TCP 连接时指定 SO_KEEPLIVE 时才会生效,当发送方和接收方长时间没有进行数据交互时,该定时器可以用于确定对端是否还活着。
  • FIN_WAIT_2 定时器:当主动请求关闭的一方发送 FIN 报文给接收端并且收到其对 FIN 的确认 ACK后进入 FIN_WAIT_2状态。如果这个时候因为网络突然断掉、被动关闭的一端宕机等原因,导致请求方没有收到接收方发来的 FIN,主动关闭的一方会一直等待。该定时器的作用就是为了避免这种情况的发生。当该定时器超时的时候,请求关闭方将不再等待,直接释放连接。
  • TIME_WAIT 定时器:在 TCP 四次挥手中,发送方在最后一次挥手之后会进入 TIME_WAIT 状态,不直接进入 CLOSE 状态的主要原因是被动关闭方万一在超时时间内没有收到最后一个 ACK,则会重发最后的 FIN,2 MSL(报文段最大生存时间)等待时间保证了重发的 FIN 会被主动关闭的一段收到且重新发送最后一个 ACK 。还有一个原因是在这 2 MSL 的时间段内任何迟到的报文段会被接收方丢弃,从而防止老的 TCP 连接的包在新的 TCP 连接里面出现。

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 万 是没问题的。

为什么服务端易受到 SYN 攻击

SYN FLOOD 是什么?

SYN Flood 是种典型的 DoS(拒绝服务)攻击,其目的是通过消耗服务器所有可用资源使服务器无法用于处理合法请求。通过重复发送初始连接请求(SYN)数据包,攻击者能够压倒目标服务器上的所有可用端口,导致目标设备根本不响应合法请求。

在 TCP 建立连接的过程中,因为服务端不确定自己发给客户端的 SYN-ACK 消息或客户端反馈的 ACK 消息是否会丢在半路,所以会给每个待完成的半开连接状态设一个定时器,如果超过时间还没有收到客户端的 ACK 消息,则重新发送一次 SYN-ACK 消息给客户端,直到重试超过一定次数时才会放弃。
服务端为了维持半开连接状态,需要分配内核资源维护半开连接。当攻击者伪造海量的虚假 IP 向服务端发送 SYN 包时,就形成了 SYN FLOOD 攻击。攻击者故意不响应 ACK 消息,导致服务端被大量注定不能完成的半开连接占据,直到资源耗尽,停止响应正常的连接请求。

解决方法:

  • 直接的方法是提高 TCP 端口容量的同时减少半开连接的资源占用时间,然而该方法只是稍稍提高了防御能力;
  • 部署能够辨别恶意 IP 的路由器,将伪造 IP 地址的发送方发送的 SYN 消息过滤掉,该方案作用一般不是太大;

上述两种方法虽然在一定程度上能够提高服务器的防御能力,但是没有从根本上解决服务器资源消耗殆尽的问题,而以下几种方法的出发点都是在发送方发送确认回复后才开始分配传输资源,从而避免服务器资源消耗殆尽。

  • SYN Cache:该方法首先构造一个全局 Hash Table,用来缓存系统当前所有的半开连接信息。在 Hash Table 中的每个桶的容量大小是有限制的,当桶满时,会主动丢掉早来的信息。当服务端收到一个 SYN 消息后,会通过一个映射函数生成一个相应的 Key 值,使得当前半连接信息存入相应的桶中。当收到客户端正确的确认报文后,服务端才开始分配传输资源块,并将相应的半开连接信息从表中删除。和服务器传输资源相比,维护表的开销要小得多。
  • SYN Cookies:该方案原理和 HTTP Cookies 技术类似,服务端通过特定的算法将半开连接信息编码成序列号或者时间戳,用作服务端给客户端的消息编号,随 SYN-ACK 消息一同返回给连接发起方,这样在连接建立完成前服务端不保存任何信息,直到发送方发送 ACK 确认报文并且服务端成功验证编码信息后,服务端才开始分配传输资源。若请求方是攻击者,则不会向服务端会 ACK 消息,由于未成功建立连接,因此服务端并没有花费任何额外的开销。

然而该方案也存在一些缺点,由于服务端并不保存半开连接状态,因此也就丧失了超时重传的能力,这在一定程度上降低了正常用户的连接成功率。此外,客户端发送给服务端的确认报文存在传输丢失的可能,当 ACK 确认报文丢失时,服务端和客户端会对连接的成功与否产生歧义,此时就需要上层应用采取相应的策略进行处理了。

  • SYN Proxy:在客户端和服务器之间部署一个代理服务器,类似于防火墙的作用。通过代理服务器与客户端进行建立连接的过程,之后代理服务器充当客户端将成功建立连接的客户端信息发送给服务器。这种方法基本不消耗服务器的资源,但是建立连接的时间变长了(总共需要 6 次握手)。

高并发服务器客户端主动关闭连接和服务端主动关闭连接的区别

以下是针对 TCP 服务来说的:

  • 服务端主动关闭连接。在高并发场景下,当服务端主动关闭连接时,此时服务器上就会有大量的连接处于 TIME-WAIT 状态。
  • 客户端主动关闭连接。当客户端主动关闭连接时,我们并不需要关心 TIME-WAIT 状态过多造成的问题,但是需要关注服务端保持大量的 CLOSE-WAIT 状态时会产生的问题。

无论是客户端还是服务器主动关闭连接,从本质上来说,在高并发场景下主要关心的就是服务端的资源占用问题,而这也是采用 TCP 传输协议必须要面对的问题,其问题解决的出发点也是如何处理好服务质量和资源消耗之间的关系。

UDP数据包结构

在这里插入图片描述
首部字段只有 8 个字节,包括源端口(16位)、目的端口(16位)、长度、检验和(该字段用于发现头部信息和数据中的错误)。12 字节的伪首部是为了计算检验和临时添加的。

常见题

UDP 用户数据报的首部十六进制表示是:06 32 00 45 00 1C E2 17,试求源端口、目的端口、 用户数据报的总长度、数据部分长度。这个用户数据报是从客户发送给服务器发送给客户?使用 UDP 的这个服务器程序是什么?

UDP数据报由首部字段和数据字段组成,其中首部占8个字节(TCP数据报首部占20字节),格式如下:
在这里插入图片描述
UDP数据报的总长度28字节,由于UDP数据报的首部占8字节,所以数据字段长度占20字节。因为目的端口号 69 < 1023,是常用的服务端口,所以这个数据报是发往服务器端的。
0~1023:常用的服务端口;
1024 ~ 49151:被注册的端口,也称为“用户端口”。1024 ~ 5000为临时端口。
端口号为69,服务器程序是TFTP。端口号53,服务器程序为DNS。
TCP/UDP端口列表: TCP/UDP端口列表

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

UDP 只有一个 socket 接收缓冲区,没有 socket 发送缓冲区,即只要有数据就发,不管对方是否可以正确接收。而在对方的 socket 接收缓冲区满了之后,新来的数据报无法进入到 socket 接受缓冲区,此数据报就会被丢弃,因此 UDP 不能保证数据能够到达目的地,此外,UDP 也没有流量控制和重传机制,故UDP的数据传输是不可靠的。
和 TCP 建立连接时采用三次握手不同,UDP 中调用 connect 只是把对端的 IP 和 端口号记录下来,并且 UDP 可多多次调用 connect 来指定一个新的 IP 和端口号,或者断开旧的 IP 和端口号(通过设置 connect 函数的第二个参数)。和普通的 UDP 相比,调用 connect 的 UDP 会提升效率,并且在高并发服务中会增加系统稳定性。
当 UDP 的发送端调用 bind 函数时,就会将这个套接字指定一个端口,若不调用 bind 函数,系统内核会随机分配一个端口给该套接字。当手动绑定时,能够避免内核来执行这一操作,从而在一定程度上提高性能。

TCP 和 UDP

TCP 的主要特点是什么?

  • TCP 是面向连接的。只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。每一条 TCP 连接只能有两个端点,只能是一对一的;
  • TCP通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输。
  • TCP 提供可靠交付的服务。通过 TCP 连接传送的数据无差错、不丢失、不重复、并且按序到达;可以进行丢包的重发控制,还可以对次序乱掉的分包进行顺序控制。
  • TCP 提供全双工通信,通信双方的应用进程在任何时候都能收发数据。TCP 连接的两端都设有发送缓存和接收缓存,用来临时存放双方通信的数据;
  • 面向字节流。含义是:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但 TCP 把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。TCP 中的“流”(Stream)指的是流入进程或从进程流出的字节序列。

TCP优点:提供可靠的,稳定的,面向连接的传输服务(TCP 的可靠体现在TCP在传递数据之前,会有三次握手来建立连接;而且在数据传递时,有确认、窗口、重传、拥塞控制机制;在数据传完后,还会断开连接用来节约系统资源)。TCP不提供广播或多播服务。

TCP缺点:慢,效率低,占用系统资源高,易被攻击。TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量时间。而且要在每台设备上维护所有的传输连接,每个连接都会占用系统的CPU、内存等硬件资源。而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。

UDP 的主要特点是什么?

  • UDP是无连接的;即UDP 不需要和 TCP一样在发送数据前进行三次握手建立连接,想发数据就可以发。并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作;

具体来说就是:
在发送端,应用层将数据传递给传输层的 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下是UDP 协议,然后就传递给网络层了;
在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报文头就传递给应用层,不会任何拼接操作。

  • UDP是面向报文的;发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。因此,应用程序必须选择合适大小的报文;
  • UDP不保证可靠交付,只尽最大努力交付,因此主机不需要维持复杂的链接状态(有许多参数);
  • UDP传输途中如果出现丢包,不负责重发。当包的到达顺序乱掉时也没有纠正的功能。UDP将部分控制转移到应用程序去处理,自己却只提供作为传输层协议的最基本功能。
  • UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如直播,实时视频会议等);
  • UDP 支持一对一、一对多、多对一和多对多的交互通信,提供了单播,多播,广播的功能;
  • UDP 的首部开销小,只有 8 个字节,比 TCP 的 20 个字节的首部短。

UDP的优点:快,比TCP稍安全。UDP 在传送数据之前不需要先建立连接,远地主机在收到 UDP 报文后,不需要给出任何确认。UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击。

UDP的缺点:不可靠,不稳定。因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。

TCP 和 UDP 的区别?

  • TCP面向连接(如打电话要先拨号建立连接)。UDP是无连接的,即发送数据之前不需要建立连接;
  • TCP提供可靠的服务,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达。UDP尽最大努力交付,即不保证可靠交付;
  • TCP面向字节流,实际上TCP把数据看成一连串无结构的字节流。UDP是面向报文的。UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等);
  • 每一条TCP连接只能是点到点的。UDP支持一对一,一对多,多对一和多对多的交互通信;
  • TCP对系统资源要求较多,UDP对系统资源要求较少。TCP首部开销20字节,UDP的首部开销小,只有8个字节;
  • TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。
TCPUDP
是否面向连接面向连接无连接
传输可靠性可靠不可靠
传输形式字节流数据报文段
传输效率
所需资源
应用场景要求通信数据可靠,如:文件传输、邮件传输要求通信速度高,如:域名转换、视频、直播
首部字节20 - 608

什么时候用TCP,什么时候用UDP?

什么时候应该使用TCP:当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。日常生活中常见的TCP协议的应用如下:浏览器,用的HTTP;FlashFXP,用的FTP;Outlook,用的POP、SMTP;Putty,用的Telnet、SSH;QQ文件传输。

什么时候应该使用UDP:一般用于即时通信,当对网络通讯质量、可靠性要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP,比如:语音、视频、直播等等。

为什么有时候UDP比TCP更有优势?

UDP以其简单、传输快的优势,在越来越多场景下取代了TCP,如实时游戏。
(1)网速的提升给UDP的稳定性提供可靠网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。
(2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。
采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大。基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性能造成的影响。

单播、多播和广播的区别

单播

主机之间“一对一”的通讯模式,是指在计算机网络的传输中,目的地址为单一目标的一种传输方式。网络中的交换机和路由器对数据只进行转发不进行复制。现今在网络应用最为广泛,通常所使用的网络协议或服务大多采用单播传输,如基于TCP的协议。IP网络的多播一般通过多播IP地址来实现。多播IP地址就是D类IP地址,即224.0.0.0至239.255.255.255之间的IP地址。DHCP管理器支持多播IP地址的自动分配。

单播的优点:

  1. 服务器及时响应客户机的请求;并有纠错机制(丢包、错包可以弥补)。
  2. 服务器针对每个客户不同的请求发送不同的数据,容易实现个性化服务。

单播的缺点:

  1. 服务器针对每个客户机发送数据流,服务器流量=客户机数量×客户机流量;在客户数量大、每个客户机流量大的流媒体应用中服务器不堪重负。
  2. 现有的网络带宽是金字塔结构,城际、省际主干带宽仅仅相当于其所有用户带宽之和的5%。如果全部使用单播协议,将造成网络主干不堪重负。

多播

也叫组播,多点广播或群播,主机之间“一对一组”的通讯模式。指把信息同时传递给一组目的地址的传输方式。网络中的交换机和路由器只向有需求者复制并转发其所需数据。它使用策略是最高效的,因为消息在每条网络链路上只需传递一次,而且只有在链路分叉的时候,消息才会被复制。

组播的优点:

  1. 需要相同数据流的客户端加入相同的组共享一条数据流,节省了服务器的负载。具备广播所具备的优点。
  2. 由于组播协议是根据接受者的需要对数据流进行复制转发,所以服务端的服务总带宽不受客户接入端带宽的限制。IP协议允许有2亿6千多万个(268435456)组播,所以其提供的服务可以非常丰富。
  3. 此协议和单播协议一样允许在Internet宽带网上传输。

组播的缺点:

  1. 与单播协议相比没有纠错机制,发生丢包、错包后难以弥补,但可以通过一定的容错机制和QOS加以弥补。
  2. 现行网络都支持组播的传输,但在客户认证、QOS等方面还需要完善。

广播

主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无条件复制并转发,所有主机都可以接收到所有信息(不管你是否需要),如有线电视网。在IP网络中,广播地址用IP地址“255.255.255.255”来表示,这个IP地址代表同一子网内所有的IP地址。

广播的优点:

  1. 网络设备简单,维护简单,布网成本低廉
  2. 由于服务器不用向每个客户机单独发送数据,所以服务器流量负载极低。

广播的缺点:

  1. 无法针对每个客户的要求和时间及时提供更多样化、更个性化的服务。
  2. 网络允许服务器提供数据的带宽有限,客户端的最大带宽=服务总带宽。例如有线电视的客户端的线路支持100个频道(如果采用数字压缩技术,理论上可以提供500个频道)。
  3. 广播禁止在Internet宽带网上传输。
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值