接上篇《通俗易懂图解网络面试知识—第一篇》
关于网络的知识,上篇学习了网络层的知识,今天我们学习一下传输层协议的知识。
UDP协议
UDP协议简介
UDP 是User Datagram Protocol的简称,中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 模型中一种无连接的传输层协议,提供面向事务的简单不可靠的信息传送服务。
UDP特点
UDP主要特点有无连接状态,无需建立连接,分组首部开销小,速度快等。所以UDP一般使用在流媒体应用,语音交流,视频会议应用。
- 无连接状态:UDP协议发送数据之前不需要建立连接,减少了开销和发送数据之前的时延。TCP需要在端系统中维护连接状态,连接状态包括接收和发送缓存、拥塞控制参数以及序号和确认号的参数等。
- 无需建立连接:UDP无需任何准备即可进行数据传输,UDP是没有时延的。而TCP 在数据传输之前需要经过三次握手的操作。
- 分组首部开销小:UDP 首部仅仅只有 8 字节的开销,TCP 报文段都有 20 字节的首部开销。
- 速度快:使用UDP协议,只要应用进程把数据传给UDP,UDP就会将数据打包进UDP报文段立即传递给网络层,而 TCP 有拥塞控制的功能,它会在发送前判断互联网的拥堵情况,如果互联网极度阻塞,那么就会抑制 TCP 的发送方 TCP 有拥塞控制的功能,它会在发送前判断互联网的拥堵情况,如果互联网极度阻塞,那么就会抑制 TCP 的发送方。
- UDP复用和分用:发送方可能有多个进程需要发送数据报,UDP从不同的进程接收数据报,每个进程都分配一个端口号。在加上UDP报头之后,UDP将数据报送往网络层。发送方的UDP处理多个进程的数据报称为UDP复用。接收方根据接收的每个进程的端口号分别处理称为UDP分用。其实这个复用和分用只是UDP的一种聚合的功能,因为本身UDP协议是有目的端口和源端口,多进程发送和接口都是基于端口,显然这样就能实现多进程的复用和分用了。
了解了UDP协议的特点,我们从OSI的模型上看下UDP封包的流程图:
- 应用数据通过应用进程端口发送,组装成应用报文。
- 应用层报文数据在传输层添加UDP首部称UDP段。
- UDP段在网络层添加IP首部称IP数据包。
- IP数据包到数据链路层添加以太网帧首部和尾部组合成以太网帧。
- 最后,帧被转换为比特,通过网络介质传输。这种协议栈逐层向下传递数据,并添加报头和报尾的过程称为封装。如果逐层向上传递数据,出现去除报头和报尾的过程叫解包。
UDP协议报文组成部分
UDP协议由四个部分组成,源端口号,目的端口号,UDP长度,UDP校验和,UDP的首部是由8个字节组成,每个组成部分占2个字节,也就是16位。下面我们看下协议报文图:
- 源、目标端口号字段:占16比特。作用与TCP数据段中的端口号字段相同,用来标识源端和目标端的应用进程。
- 长度字段:占16比特。标明UDP头部和UDP数据的总长度字节。
- 校验和字段:占16比特。用来对UDP头部和UDP数据进行校验。和TCP不同的是,对UDP来说,此字段是可选项,而TCP数据段中的校验和字段是必须有的。
UDP服务实现
UDP协议和TCP协议在工作方式是不同的,但是他们都是建立了端口到端口的通信。端口(port)是伴随着传输层诞生的概念。实现一个UDP通信服务实现是调用操作系统的API来构建socket,socket是操作系统的一种编程接口,它代表某个网络通信。下面我们图解一下UDP基于编程接口的调用实现。
IP协议和UDP都是无连接的,IP协议主要是通过IP地址进行投递目标主机,UDP是通过端口投递到指定的网络应用程序。
TCP协议
TCP协议简介
TCP协议是传输控制协议,面向连接的,在不可靠的互联网上提供可靠的,全双工通信服务传输协议。TCP提供传输连接管理机制,差错控制,流量控制,拥塞控制等。
TCP特点
TCP协议的主要特点是面向连接,全双工通信,建立和释放可靠的连接,流量控制和拥塞控制,支持流接口。
- 面向连接:源进程在指定的端口和目的进程指定的端口建立传输连接,一旦这个连接建立之后,通信的两个进程就可以在这个连接上发送和接受数据流。面向连接的传输服务可以很好地保证数据流传输的可靠性。
- 全双工通信:全双工概念:可以同时进行信号的双向传输(A->B且B->A)。TCP允许全双工通信。在两个应用进程传输连接建立后,客户与服务器进程可以同时发送和接收数据流。TCP在发送和接收方都使用缓存机制,发送缓存用来存储进程准备发送的数据,接收缓存在收到报文段之后,将它们存储在接收缓存中,等待接收进程读取对方传送来的数据。
- 建立和释放可靠的连接:为了保证传输连接建立和释放的可靠性,TCP在连接建立阶段防止出现因失效的连接请求数据包造成请求错误,TCP使用了“三次握手”机制。在释放传输连接时,保证在关闭连接时已经发送的数据报可以全部正确的达到目的端口,TCP使用了“四次挥手”机制。
- 流量控制和拥塞控制:TCP采用了大小可以变化的滑动窗口方法进行流量控制。发送窗口大小在建立连接时由双方商定。在通信过程中,发送方可以根据自己的资源情况随机、动态地调整发送窗口的大小,而接收方将跟随发送方调整接收窗口。
- 支持流接口:TCP提供一个流接口(Stream Interface),应用进程可以利用它发送连续的数据流。TCP传输连接提供一个“管道”,保证数据流从一端正确地“流”到另一端。TCP对数据流的内容不作任何解释,数据流的解释由双方的应用程序处理。
TCP协议报文组成
TCP报文段由首部和数据两部分组成。TCP首部的前20字节是固定的,称为TCP固定首部,后面有4×N字节的选项部分。TCP协议如图:
- 源端口(Source Port)和目的端口(Destination Port):各占16位。分别表示报文的源端口号和目的端口号。
- 将TCP报文中源端口和目的端口字段加上IP报文中源IP地址和目的IP地址字段构成一个4元组<源端口,源IP地址,目的端口,目的IP地址>,它可以唯一地标识一个TCP连接。
- 序号(Sequence Number)、确认序号(Acknowledgment Number)和通告窗口(Advertised Window):序号和确认序号各占32位,通告窗口占16位。
- 首部长度(Header Length):占4位。表示TCP首部长度,该值以32位为单位计算,如TCP固定首部为20字节,则头部长度为5。
- 标志位(Flags):占6位。用于区分不同类型的TCP报文,目前用到的标志位有SYN、ACK、FIN、RST、PSH和URG。
- 校验和:与UDP中的校验和字段用法完全相同,它是通过计算整个TCP报文的首部、TCP报文的数据报以及来自IP报文首部的源地址、目的地址、协议和TCP长度字段构成的伪首部得来的。TCP报文字段中的校验和字段是必需的。
- 选项:最常用的选项字段是最大段长度(Maximum Segment Size,MSS),通常用MSS来限制报文段数据的最大长度。
TCP服务实现
TCP 网络编程有两种模式,一种是服务器模式,另一种是客户端模式。服务器模式创建一个服务程序,等待客户端用户的连接,接收到用户的连接请求后,根据用户的请求进行处理;客户端模式则根据目的服务器的地址和端口进行连接,向服务器发送请求,并对服务器的响应进行处理。
关于服务器模式的程序设计流程:
- 套接字初始化:用户对套接字的需求来确定套接字的选项。
- 套接字与端口绑定:将套接字与一个地址结构进行绑定。绑定之后,在进行网络程序设计的时候,套接字所代表的 IP 地址和端口地址以及协议类型等参数按照绑定值进行操作
- 由于一个服务器需要满足多个客户端的连接请求,而服务器在某个时刻仅能处理有限个客户端的连接请求,所以服务器需要设置服务端排队队列的长度。服务器在侦听连接时会设置这个参数,限制客户端中等待服务器处理的连接请求的队列长度
- 在客户端发送连接请求之后,可以从套接字文件描述符中读取数据或者向描述符发送数据。
- 当服务器处理完数据,要结束与客户端的通信过程的时候,需要关闭套接字连接。
关于服务器模式可以参考下图:
三次握手,四次挥手场景面试
首先我们看下TCP建立和结束示意图:
问题1:为什么是 TCP 三次握手?不是两次、四次?
- 三次握手(Three-way Handshake)其实就是指建立一个 TCP 连接时,需要客户端和服务器总共发送 3 个包。
- 进行三次握手的主要作用就是为了确认对方的接收能力和发送能力是否正常,从而为后面的可靠性传送做准备。需要三次握手才能确认对方的接收与发送能力是否正常。第一次客户端发送给服务端,服务端回复给客户端之后,客户端就能知道服务端具备发送和接收能力了,此时服务端能知道客户端具备发送能力,但是接收能力还不确定,等客户端再次回复服务端的时候,服务端能知晓客户端也具备发送和接收能力了。
- 三次握手的次要作用是减少恶意伪造数据包的用户对服务器攻击,大量攻击数据包可能占用着未完成三次握手队列,使得正常需要提供服务的连接进不来,有了第三次握手,如果服务器收不到攻击数据报的ACK,就会尝试重发SYN+ACK报文,如果多次重试,连接不上,则服务器会关闭连接,有效降低SYN攻击带来的资源损害。
问题2:为什么关闭连接的需要四次挥手?
- 当服务端收到客户端FIN数据包后(第一次挥手),服务端不会立即close,为什么不立即close,因为可能数据还没有发完,服务端会先将ACK发送告诉客户端我收到你的断开请求(第二次挥手),请给我一点时间,这段时间用来发送剩下的数据报文,发送之后再将FIN包发给客户端表示现在可以断开了(第三次挥手)。客户端收到FIN包之后发送ACK确认断开消息给服务端(第四次挥手)。
- TCP允许单向发送数据。当主动关闭方关闭连接,被动方在不调用close的状态下,可以长时间发送数据,此时连接处于半关闭状态。这一特性是TCP的双向通道相互独立导致的,也导致了关闭连接必须进行四次挥手。
问题3:为什么主动断开方在TIME-WAIT状态必须等待2MSL的时间?
- MSL(Maximum Segment Lifetime)Linux中MSL的值固定为30秒,所以TIME_WAIT的时间为60秒。
- 如果没有这个TIME_WAIT,端口可以复用于新连接了。这时被动方的FIN报文可能再次到达,可能是路由器重复发的,也可能是被动方没有收到ACK重发的。这样正常的新连接就会被重复发送的旧的FIN误关闭。保留了TIME_WAIT就可以应付重发的FIN。
- 等待2倍MSL,其实是允许ACK丢失一次,如果一个ACK丢失,被动方重发的FIN就会在第二个MSL内到达,TIME_WAIT就可以应付。
问题4:什么是SYN攻击?
- SYN(synchronous)是TCP/IP建立连接时使用的握手信号。SYN攻击属于DDoS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。
- SYN攻击解决办法:修改等待数:
sysctl -w net.ipv4.tcp_max_syn_backlog=2048
- 启用SYN Cookie,它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。
sysctl -w net.ipv4.tcp_syncookies=1
- 修改重试次数,重传次数设置为0,只要收不到客户端的响应,立即丢弃该连接,默认设置为5次
sysctl -w net.ipv4.tcp_syn_retries = 0