网络面试 100 问,和面试官扯皮绰绰有余

5/31/2024, Network

文章收录在 GitHub JavaKeeper (opens new window) ,互联网开发必备技能兵器谱,有你想要的。

# 一、计算机网络

# 通信协议

通信协议(communications protocol)是指双方实体完成通信或服务所必须遵循的规则和约定。通过通信信道和设备互连起来的多个不同地理位置的数据通信系统,要使其能协同工作实现信息交换和资源共享,它们之间必须具有共同的语言。交流什么、怎样交流及何时交流,都必须遵循某种互相都能接受的规则。这个规则就是通信协议。

# 能说说 ISO 七层模型和 TCP/IP 四层模型吗?

随着技术的发展,计算机的应用越来越广泛,计算机之间的通信开始了百花齐放的状态,每个具有独立计算服务体系的信息技术公司都会建立自己的计算机通信规则,而这种情况会导致异构计算机之间无法通信,极大的阻碍了网络通信的发展,至此为了解决这个问题,国际标准化组织(ISO)制定了 OSI 模型,该模型定义了不同计算机互联的标准,OSI 模型把网络通信的工作分为 7 层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层

这七层模型是设计层面的概念,每一层都有固定要完成的职责和功能,分层的好处在于清晰和功能独立性,但分层过多会使层次变的更加复杂,虽然不需要实现本层的功能,但是也需要构造本层的上下文,空耗系统资源,所以在落地实施网络通信模型的时候将这七层模型简化合并为四层模型分别是应用层、传输层、网络层、网络接口层(各层之间的模型、协议统称为:TCP/IP协议簇)。

img

从上图可以看到,TCP/IP 模型合并了 OSI 模型的应用层、表示层和会话层,将 OSI 模型的数据链路层和物理层合并为网络访问层。

上图还列出了各层模型对应 TCP/IP 协议栈中的协议以及各层协议之间的关系。比如 DNS 协议是建立在 TCP 和 UDP 协议的基础上,FTP、HTTP、TELNET 协议建立在 TCP 协议的基础上,NTP、TFTP、SNMP建立在UDP协议的基础上,而 TCP、UDP 协议又建立在 IP 协议的基础上,以此类推….

OSI中的层 功能 TCP/IP协议族
应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,RIP,Telnet
表示层 数据格式化,代码转换,数据加密
会话层 控制应用程序之间会话能力;如不同软件数据分发给不同软件 ASAP、TLS、SSH、ISO 8327 / CCITT X.225、RPC、NetBIOS、ASP、Winsock、BSD sockets
传输层 端到端传输数据的基本功能 TCP、UDP
网络层 定义IP编址,定义路由功能;如不同设备的数据转发 IP,ICMP,RIP,OSPF,BGP,IGMP
数据链路层 定义数据的基本格式,如何传输,如何标识 SLIP,CSLIP,PPP,ARP,RARP,MTU
物理层 二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802

当我们某一个网站上不去的时候。通常会 ping 一下这个网站

ping 可以说是 ICMP 的最著名的应用,是 TCP/IP 协议的一部分。利用 ping 命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障。

常见协议

  1. HTTP/HTTPS (Hypertext Transfer Protocol / Secure HTTP)

    • 作用:用于浏览器与服务器之间的超文本传输。
    • 特点:HTTP 是无状态协议,HTTPS 在 HTTP 基础上加入 TLS/SSL 加密,保障数据安全。
    • 用途:网页访问、API 请求等。
  2. DNS (Domain Name System)

    • 作用:将域名解析为 IP 地址,解决用户记忆困难的问题。
    • 用途:输入网址时将域名转换为对应的服务器 IP 地址。
  3. FTP/SFTP (File Transfer Protocol / Secure File Transfer Protocol)

    • 作用:用于文件上传和下载。
    • 特点:SFTP 增强了 FTP 的安全性,通过 SSH 加密传输。
  4. SMTP (Simple Mail Transfer Protocol)

    • 作用:用于电子邮件的发送。
    • 用途:邮件客户端(如 Outlook、Gmail)通过 SMTP 将邮件发送到邮件服务器。
  5. POP3/IMAP (Post Office Protocol / Internet Message Access Protocol)

    • 作用:用于接收电子邮件。
    • 区别:
      • POP3 下载邮件后默认从服务器删除。
      • IMAP 支持邮件在服务器端同步,适合多设备访问。
  6. Telnet/SSH (Secure Shell)

    • 作用:远程登录和管理服务器。
    • 特点:SSH 是 Telnet 的安全升级版,提供加密通信。
  7. TCP (Transmission Control Protocol)

    • 作用:提供可靠的、面向连接的传输服务。
    • 特点:通过三次握手建立连接、数据重传、流量控制、拥塞控制等确保数据的完整性。
    • 用途:HTTP/HTTPS、邮件传输、文件传输等需要数据可靠性的场景。
  8. UDP (User Datagram Protocol)

    • 作用:提供不可靠的、无连接的传输服务。

    • 特点:速度快、开销小,无需建立连接,可能会丢失数据。

    • 用途:实时通信(如语音、视频直播)、DNS 查询、在线游戏等对时延敏感的场景。

  9. P (Internet Protocol)

    • 作用:提供逻辑地址(IP 地址)以及数据包路由功能。
    • 特点:不保证数据传输的可靠性。
    • 版本:
      • IPv4:使用 32 位地址,地址资源有限。
      • IPv6:使用 128 位地址,解决了地址耗尽问题。
  10. ICMP (Internet Control Message Protocol)

    • 作用:用于网络诊断和错误报告。

    • 用途ping 命令通过 ICMP 测试网络连接是否畅通。

  11. ARP (Address Resolution Protocol)

    • 作用:将 IP 地址解析为物理地址(MAC 地址)。

    • 用途:局域网内通信时,通过 ARP 获取目标设备的 MAC 地址。

  12. NAT (Network Address Translation)

    • 作用:将私有 IP 地址转换为公网 IP 地址。

    • 用途:解决 IPv4 地址不足问题,支持多个设备共享一个公网 IP。

# 为什么 TCP/IP 去除了表示层和会话层

OSI 参考模型在提出时,他们的理想是非常好的,但实际上,由于会话层、表示层、应用层都是在应用程序内部实现的,最终产出的是一个应用数据包,而应用程序之间是几乎无法实现代码的抽象共享的,这也就造成 OSI 设想中的应用程序维度的分层是无法实现的,例如,我们几乎不会认为数据的压缩、加密算法算是一种协议,而会话的概念则更为抽象,难以用协议来进行描述,所以在后来的 TCP/IP 协议框架的设计中,便将表示层和会话层与应用层整合在一起,让整个过程更为清晰明了

# 二、TCP/IP 协议族

我这里没有按具体的 7 层协议去划分知识点,个人感觉从面试角度看,或者从普通后端程序员来说,主要了解的就是围绕 HTPP/HTTPS 、以及传输层的 UDP、TCP 等展开的

# 2.1 TCP vs UDP

数据在网络中传输最终一定是通过物理介质传输。物理介质就是把电脑连接起来的物理手段,常见的有光纤、双绞线,以及无线电波,它决定了电信号(0和1)的传输方式,物理介质的不同决定了电信号的传输带宽、速率、传输距离以及抗干扰性等等。网络数据传输就像快递邮寄,数据就是快件。只有路打通了,你的”快递”才能送到,因此物理介质是网络通信的基石。

寄快递首先得称重、确认体积(确认数据大小),贵重物品还得层层包裹填充物确保安全,封装,然后填写发件地址(源主机地址)和收件地址(目标主机地址),确认快递方式。对于偏远地区,快递不能直达,还需要中途转发。网络通信也是一样的道理,只不过把这些步骤都规定成了各种协议。

TCP/IP 的模型的每一层都需要下一层所提供的协议来完成自己的目的。我们来看下数据是怎么通过 TCP/IP 协议模型从一台主机发送到另一台主机的。

img

当用户通过HTTP协议发起一个请求,应用层、传输层、网络互联层和网络访问层的相关协议依次对该请求进行包装并携带对应的首部,最终在网络访问层生成以太网数据包,以太网数据包通过物理介质传输给对方主机,对方接收到数据包以后,然后再一层一层采用对应的协议进行拆包,最后把应用层数据交给应用程序处理。

# TCP/IP 与 HTTP 有什么关系吗?

TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP 协议不仅仅指的是 TCP 和 IP 两个协议,而是指一个由 FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中 TCP 协议和 IP 协议最具代表性,所以被称为 TCP/IP 协议。

而 HTTP 是应用层协议,主要解决如何包装数据。

“IP”代表网际协议,TCP 和 UDP 使用该协议从一个网络传送数据包到另一个网络。把IP想像成一种高速公路,它允许其它协议在上面行驶并找到到其它电脑的出口。TCP和UDP是高速公路上的“卡车”,它们携带的货物就是像HTTP,文件传输协议FTP这样的协议等。

# TCP协议与UDP协议的区别?

都属于传输层协议。

  • TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。一个 TCP 连接必须有三次握手、四次挥手。

  • UDP(User Data Protocol,用户数据报协议)是一个非连接的协议,传输数据之前源端和终端不建立连接, 当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上

TCP UDP
连接性 面向连接 面向非连接
传输可靠性 可靠 不可靠
报文 面向字节流 面向报文
效率 传输效率低 传输效率高
流量控制 滑动窗口
拥塞控制 慢开始、拥塞避免、快重传、快恢复
传输速度
应用场合 对效率要求低,对准确性要求高或要求有连接的场景 对效率要求高,对准确性要求低

TCP 和 UDP 协议的一些应用

img

# TCP 连接的建立与终止?

TCP 和 UDP 的报文结构了解么

TCP 虽然是面向字节流的,但TCP传送的数据单元却是报文段。一个 TCP 报文段分为首部和数据两部分,而 TCP 的全部功能体现在它首部中的各字段的作用。

TCP 报文段首部的前 20 个字节是固定的(下图),后面有 4n 字节是根据需要而增加的选项(n是整数)。因此 TCP 首部的最小长度是20 字节。

img

TCP报文首部

  • 源端口和目的端口,各占 2 个字节,都是 16 位,分别写入源端口和目的端口;
  • 序列号(Sequence number),占4字节,32位。序号范围是【0,2^32 - 1】,共2^32个序号。序号增加到 2^32-1后,下一个序号就又回到 0。TCP是面向字节流的。在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在连接建立时设置。首部中的序号字段值则是指的是本报文段所发送的数据的第一个字节的序号。例如,一报文段的序号是301,而接待的数据共有100字节。这就表明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。显然,下一个报文段(如果还有的话)的数据序号应当从401开始,即下一个报文段的序号字段值应为401。这个字段的序号也叫“报文段序号”;
  • 确认号(Acknowledge number),占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;
  • 数据偏移(Data Offset),占 4 位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。
  • 保留(Reserved),占 6 位,保留为今后使用,但目前应置为0;
  • 控制位(Control Flags)
    • 6 位,包括 URG(紧急指针有效)、ACK(确认号有效)、PSH(推送功能)、RST(重置连接)、SYN(同步序列编号)、FIN(结束连接)。
  • 窗口大小(Window Size)
    • 16 位,用于流量控制,指示接收方的接收窗口大小。
  • 校验和(Checksum)
    • 16 位,用于错误检测,对 TCP 头部和数据部分进行校验。
  • 紧急指针(Urgent Pointer)
    • 16 位,仅当 URG 标志位被设置时使用,指向数据中紧急数据的末尾。
  • 选项(Options)
    • 可变长度,用于设置 TCP 参数,如最大报文段长度(MSS)、窗口缩放因子、选择性确认(SACK)等。
  • 填充(Padding)
    • 确保 TCP 头部是 32 位字的整数倍。
  • 数据(Data)
    • TCP 报文的实际数据部分,长度可变。

# 介绍一下 TCP 的三次握手机制,为什么要三次握手?挥手却又是四次呢?

TCP是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务器的内存里保存的一份关于对方的信息,如ip地址、端口号等。

# TCP 三次握手

所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送 3 个包。

三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。

img

  • 第一次握手(SYN):客户端向服务器发送一个SYN(Synchronize)报文段,用于请求建立连接。这个报文段包含客户端的初始序列号(ISN),用于同步序列号。

  • 第二次握手(SYN-ACK):服务器收到SYN报文后,确认收到请求,并向客户端发送一个SYN-ACK(Synchronize-Acknowledgment)报文。这个报文段包含服务器的初始序列号,并确认接收到的客户端的序列号。

  • 第三次握手(ACK):客户端收到服务器的SYN-ACK报文后,再次向服务器发送一个ACK(Acknowledgment)报文,确认收到服务器的序列号。至此,连接建立完毕,客户端和服务器可以开始数据传输。

# 为什么需要三次握手呢?两次不行吗?
  • 确保双向通信:三次握手可以确保通信的双向性。通过三次握手,客户端和服务器都确认了对方的存在,并且双方都同步了初始序列号,为接下来的数据传输做准备。

  • 防止旧连接的混淆:如果只有两次握手,可能会存在旧的、失效的 SYN 报文被误认为是新的连接请求,导致混淆。三次握手能够有效避免这种情况。

具体例子:“已失效的连接请求报文段”的产生在这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

# TCP 四次挥手

TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手。客户端或服务器均可主动发起挥手动作

img

  • 第一次挥手(FIN=1,seq=x)

    主机1(可以是客户端,也可以是服务器端),设置seq=x,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机 1 没有数据要发送给主机2了;

  • 第二次挥手(ACK=1,ACKnum=x+1)

    主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknum=x+1,主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;

  • 第三次挥手(FIN=1,seq=y)

    主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK 状态

  • 第四次挥手(ACK=1,ACKnum=y+1)

    主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了,进入 CLOSED 状态。

第一个消息:A发FIN

第二个消息:B回复ACK

第三个消息:B发出FIN

此时此刻:B单方面认为自己与A达成了共识,即双方都同意关闭连接。

此时,B能释放这个TCP连接占用的内存资源吗?不能,B一定要确保A收到自己的ACK、FIN。

所以B需要静静地等待A的第四个消息的到来:

第四个消息:A发出ACK,用于确认收到B的FIN

主机 1 等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。

MSL 是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。

Linux 系统:默认 MSL 通常为 60 秒(可通过 /proc/sys/net/ipv4/tcp_fin_timeout 查看),因此 2MSL 对应 120 秒(120,000 毫秒)

# 为什么连接的时候是三次握手,关闭的时候却是四次握手?
  • 全双工通信的特性:TCP是全双工通信协议,双方的发送和接收通道是独立的。在关闭连接时,双方都需要独立地关闭各自的发送和接收通道,因此需要四次挥手。

  • 确保数据完整传输:四次挥手允许双方有机会处理完所有未发送的数据。即使主动关闭一方不再发送数据,被动关闭一方仍然可以继续发送尚未传输完毕的数据,直到确认所有数据都已接收。

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

由于 TCP 协议是全双工的,也就是说客户端和服务端都可以发起断开连接。两边各发起一次断开连接的申请,加上各自的两次确认,看起来就像执行了四次挥手

为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

MSL(Maximum Segment Lifetime)是TCP报文在网络中可以存在的最长时间,2MSL 是两倍的这个时间

虽然按道理,四个报文都发送完毕,我们可以直接进入 CLOSE 状态了,但是我们必须假想网络是不可靠的,有可能最后一个ACK丢失。所以 TIME_WAIT 状态就是用来重发可能丢失的 ACK 报文。

还有一个原因,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个 2MSL 时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

# TCP 协议如何来保证传输的可靠性?

如何设计一个稳定的 UDP 协议, 也可以参考这个回答

  1. 数据分段与重组

    • 分段:TCP将应用层数据分割成多个数据段(segment),每个数据段都附有一个序列号(Sequence Number),用于标识该段在整个数据流中的位置。

    • 重组:接收方根据序列号将接收到的数据段重新组装成原始数据,确保数据按正确的顺序传递给应用层。

  2. 确认应答机制(Acknowledgment)

    • 确认(ACK):接收方在收到数据段后,会向发送方发送一个确认(ACK)报文,告知发送方已成功接收到数据段,并且表明下一个期望接收的数据段的序列号。

    • 超时重传:发送方在发送数据段后,会启动一个定时器,如果在一定时间内没有收到接收方的ACK报文,发送方会认为数据段丢失,并重新发送该数据段。

  3. 滑动窗口机制(Sliding Window)

    • 窗口大小:TCP使用滑动窗口来控制发送方可以连续发送而不必等待确认的最大数据量。窗口大小是动态调整的,取决于接收方的处理能力和网络的实际状况。

    • 流量控制:滑动窗口机制还实现了流量控制,防止发送方发送过多的数据段,导致接收方无法及时处理,从而引发网络拥塞或数据丢失。

  4. 重传机制

    • 超时重传:如果发送方在预定的时间内没有收到ACK,TCP会触发超时重传,将未被确认的数据段重新发送。

    • 快速重传:当接收方发现数据段丢失时,会发送多个重复的ACK报文,发送方在收到三个相同的ACK报文后,不等待定时器超时,直接重传丢失的数据段。

  5. 拥塞控制

    • 拥塞避免(Congestion Avoidance):一旦到达拥塞阈值,窗口大小增长速度会放缓,采取线性增长方式,以进一步防止拥塞。

    • 快速恢复(Fast Recovery):在快速重传后,发送方会将窗口大小减半,并继续数据传输,而不进入慢启动阶段,尽量保持网络效率。

  6. 数据校验

    • 校验和(Checksum):每个TCP报文段都包含一个校验和字段,用于验证数据在传输过程中是否被修改。接收方会计算收到的数据段的校验和,并与报文段中的校验和进行比较,如果不匹配,则认为数据有误,丢弃该段,并请求重传。
  7. 序列号与确认号

    • 序列号(Sequence Number):用于标识发送的数据段在数据流中的位置。

    • 确认号(Acknowledgment Number):用于通知发送方下一个期望接收的数据段的序列号。序列号与确认号结合使用,确保所有数据段都能被正确接收和重组。

  8. 连接管理(Connection Management)

  • 三次握手:在建立连接时,通过三次握手机制确认通信双方都已准备好,确保连接的可靠性。

  • 四次挥手:在断开连接时,通过四次挥手机制确保双方都已经完成数据传输,安全地关闭连接。

通过以上这些机制,TCP能够在一个不可靠的网络环境中,提供端到端的可靠数据传输服务。这些机制确保数据完整、有序地传输,并能够适应网络中的动态变化。

# 详细讲一下TCP的滑动窗口?知道流量控制和拥塞控制吗?

# 滑动窗口机制

如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。

利用滑动窗口机制可以很方便地在 TCP 连接上实现对发送方的流量控制。

img

TCP的滑动窗口机制是一种流量控制技术,用于在不需要等待每个数据包的确认的情况下,实现高效的数据传输。滑动窗口机制允许发送方在等待确认之前发送多个数据段,这样可以更好地利用网络带宽,提高数据传输效率。

从上面的图可以看到滑动窗口左边的是已发送并且被确认的分组,滑动窗口右边是还没有轮到的分组。

滑动窗口里面也分为两块,一块是已经发送但是未被确认的分组,另一块是窗口内等待发送的分组。随着已发送的分组不断被确认,窗口内等待发送的分组也会不断被发送。整个窗口就会往右移动,让还没轮到的分组进入窗口内。

滑动窗口的工作原理

  1. 窗口大小(Window Size):滑动窗口的大小表示发送方在等待接收方确认之前,可以发送的未确认数据段的总量。窗口大小是一个动态的值,由接收方通过TCP报文中的窗口字段(window field)告知发送方。
  2. 发送窗口(Send Window):发送方维护一个发送窗口,表示可以发送的数据段范围。窗口左边界是已确认的数据段,右边界是窗口的大小。发送方可以在发送窗口范围内连续发送数据段,而无需等待前一个数据段的确认。
  3. 接收窗口(Receive Window):接收方也维护一个接收窗口,表示可以接收的数据段范围。接收方会根据自己的缓冲区大小,动态调整接收窗口的大小,并通过ACK报文通知发送方。
  4. 窗口滑动:每当发送方收到接收方的ACK确认报文时,窗口会向前滑动,允许发送方继续发送更多的数据段。窗口的滑动意味着已确认的数据段从发送窗口中移出,新的未发送数据段可以加入发送窗口。
# TCP的拥塞处理

计算机网络中的带宽、交换结点中的缓存及处理机等都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏,这种情况就叫做拥塞。拥塞控制就是防止过多的数据注入网络中,这样可以使网络中的路由器或链路不致过载。注意,拥塞控制和流量控制不同,前者是一个全局性的过程,而后者指点对点通信量的控制。拥塞控制的方法主要有以下四种:

  1. 慢启动:不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小;

  2. 拥塞避免:拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,而不是加倍,这样拥塞窗口按线性规律缓慢增长。

    TCP拥塞避免算法:

    • TCP Tahoe 是早期的拥塞控制算法之一:
      • 慢启动:发送窗口(cwnd)从1个MSS开始,指数增长,直到达到拥塞阈值(ssthresh)。
      • 拥塞避免:达到 ssthresh 后,cwnd 线性增长
      • 拥塞检测:通过超时或重复ACK判断拥塞,一旦检测到拥塞,cwnd 和 ssthresh 都会重置,重新进入慢启动阶段。
    • TCP Reno 是 TCP Tahoe 的改进版:引入了快速重传机制,当收到三个重复ACK时,直接重传丢失的数据包,而不是等待超时。
    • NewReno 算法、Vegas 算法 等
  3. 快重传:快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。

  4. 快恢复:快重传配合使用的还有快恢复算法,当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh 门限减半,但是接下去并不执行慢开始算法:因为如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将 cwnd 设置为ssthresh 的大小,然后执行拥塞避免算法。

# 滑动窗口、流量控制与拥塞控制的关系
  • 滑动窗口:是TCP实现高效数据传输的基本机制,它在不等待每个数据段确认的情况下,允许发送多个数据段。这一机制与流量控制和拥塞控制密切相关。
  • 流量控制:通过接收窗口的调整,控制发送方的发送速度,确保接收方能够处理接收到的数据。
  • 拥塞控制:通过动态调整拥塞窗口(cwnd),管理发送方的发送速率,以防止网络拥塞,确保网络的稳定性和数据传输的可靠性。

# TCP 连接client和server有哪些状态?

在 TCP 连接建立和断开过程中,客户端和服务器会经历一系列状态转换,这些状态定义了 TCP 连接的不同阶段。了解这些状态有助于理解 TCP 如何建立、维护和终止连接。

TCP连接的主要状态

  1. CLOSED:初始状态。这个状态表示连接未建立或者已关闭。
    • 适用对象:客户端或服务器在启动前或连接结束后。
  2. LISTEN:服务器处于监听状态,等待客户端发起连接请求。
    • 适用对象:服务器。
  3. SYN-SENT:客户端发送了SYN报文并等待服务器的SYN-ACK响应。这是三次握手的第一步。
    • 适用对象:客户端。
  4. SYN-RECEIVED:服务器收到客户端的SYN报文后,发送SYN-ACK报文,并等待客户端的ACK。这是三次握手的第二步。
    • 适用对象:服务器。
  5. ESTABLISHED:连接已经建立,客户端和服务器可以进行数据传输。
    • 适用对象:客户端和服务器。
  6. FIN-WAIT-1:客户端或服务器主动关闭连接,发送FIN报文,并等待对方的ACK。
    • 适用对象:主动关闭连接的一方。
  7. FIN-WAIT-2:主动关闭连接的一方收到对方的ACK后,进入FIN-WAIT-2状态,等待对方发送FIN报文。
    • 适用对象:主动关闭连接的一方。
  8. CLOSE-WAIT:被动关闭连接的一方收到FIN报文后,发送ACK并进入CLOSE-WAIT状态。此时,这一方准备关闭连接,但可能还有未处理的数据。
    • 适用对象:被动关闭连接的一方。
  9. CLOSING:双方几乎同时发送FIN报文。此时双方都在等待对方的ACK。
    • 适用对象:客户端或服务器。
  10. LAST-ACK:被动关闭连接的一方在发送了自己的FIN报文并收到ACK后,进入LAST-ACK状态,等待最后一个ACK的到来。
    • 适用对象:被动关闭连接的一方。
  11. TIME-WAIT:主动关闭连接的一方在发送最后的ACK报文后进入TIME-WAIT状态,等待一段时间,以确保对方收到ACK。如果在此期间未收到对方的任何数据包,连接最终关闭。
    • 适用对象:主动关闭连接的一方。
  12. CLOSED:连接最终关闭,所有资源释放。
    • 适用对象:客户端和服务器。

# 服务器出现了大量 CLOSE_WAIT 状态如何解决?

大量 CLOSE_WAIT 表示程序出现了问题,对方的 socket 已经关闭连接,而我方忙于读或写没有及时关闭连接,需要检查代码,特别是释放资源的代码,或者是处理请求的线程配置。

# 讲一讲SYN超时,洪泛攻击,以及解决策略

SYN 超时是指在 TCP 三次握手的过程中,客户端发送了 SYN 包,但由于网络问题或服务器未响应,客户端在等待 SYN-ACK 包的过程中发生了超时。

解决策略

  1. 重试机制:客户端在发生 SYN 超时时,会重试发送 SYN 包。一般情况下,TCP 协议会尝试重发 SYN 包若干次,直到达到最大重试次数。如果超过最大重试次数仍未收到 SYN-ACK 包,TCP 会放弃连接建立。
  2. 调整超时时间:根据网络环境调整 SYN 包的超时时间和重试次数,以适应网络的实际情况,确保在合理的时间内重试足够多次。
  3. 网络诊断:使用网络诊断工具(如 pingtraceroutetcpdump)检查网络路径是否存在问题,排查网络设备和路由的故障。
# 什么是 SYN 洪泛攻击?

SYN 洪泛攻击(SYN Flood Attack) 是一种经典的 拒绝服务攻击(DoS, Denial of Service) 或分布式拒绝服务攻击(DDoS)方式。攻击者通过向目标服务器发送大量伪造的 TCP SYN 请求包,试图耗尽服务器的资源(如内存、CPU 或连接表),从而导致服务器无法正常处理合法用户的请求。

解决策略

  1. SYN Cookies:SYN Cookies 是一种防御 SYN 洪泛攻击的技术。服务器在收到 SYN 包时,不立即分配资源,而是生成一个特殊的序列号(Cookie)并发送给客户端。如果客户端返回正确的 Cookie,服务器才分配资源并建立连接。
  2. 限制半开连接数量:配置服务器限制半开连接(即已发送 SYN-ACK 但未收到 ACK)的数量。当半开连接数量达到限制时,新的 SYN 请求将被丢弃或延迟处理。
  3. 缩短超时时间:减小半开连接的超时时间,使得服务器更快地释放未完成的连接资源。
  4. 网络层防护:使用防火墙和入侵检测系统(IDS)来过滤和阻止可疑的 SYN 包。可以配置防火墙规则来限制每秒钟的 SYN 包数量,或者启用流量分析来检测和防御洪泛攻击。
  5. 负载均衡:通过部署负载均衡器,将流量分散到多个服务器,从而缓解单个服务器的负载压力,提高抗攻击能力。
  6. 云服务防护:利用云服务提供商的安全防护措施(如 DDoS 防护服务),通过全球分布的节点和强大的处理能力来抵御大规模的洪泛攻击。

# linux 最多可以建立多少个tcp连接,client端,server端,超过了怎么办?

Linux系统上TCP连接的数量限制主要受以下几个因素影响:

  1. 文件描述符限制:Linux系统中每个进程可以打开的文件描述符数量是有限的。可以通过修改/etc/security/limits.conf文件来调整这一限制,例如设置* soft nofile 65535* hard nofile 65535来分别设置软限制和硬限制 。
  2. 系统级文件打开限制:Linux系统级也有一个最大文件打开数量的硬限制,可以通过/proc/sys/fs/file-max查看和设置。如果需要,可以通过修改/etc/rc.local脚本来调整这个限制 。
  3. 端口范围限制:TCP连接的端口范围通常是0到65535,其中1024以下的端口通常保留给系统或特殊用途。因此,对于用户应用来说,可以使用的端口数大约为65535 - 1024 = 64511个。 客户端通常在临时端口范围内分配端口,默认范围在32768到60999之间(根据系统不同而不同),因此单个客户端最多能建立约28000个连接。可以通过调整/proc/sys/net/ipv4/ip_local_port_range来扩展这个范围。
  4. TCP连接跟踪限制:Linux内核的网络防火墙模块会对TCP连接状态进行跟踪,这需要内存资源。可以通过修改/etc/sysctl.conf文件中的net.ipv4.ip_conntrack_max来调整TCP连接跟踪的最大数量 。
  5. 内核参数:Linux内核的多个参数影响TCP连接数,例如net.core.netdev_max_backlog(网络设备接收队列的最大包数)、net.ipv4.somaxconn(监听套接字的 backlog 限制)、net.ipv4.tcp_max_orphans(没有文件句柄的TCP套接字的最大数量)等。这些参数可以通过sysctl命令或/etc/sysctl.conf文件进行调整 。
  6. 编程技术:使用支持高并发网络I/O的编程技术,如epoll或AIO,可以提高程序对高并发TCP连接的支持 。
  7. 防火墙规则:防火墙规则可能限制了最大连接数,例如使用iptables的-A INPUT -p tcp --syn --dport命令可以限制每个IP地址的连接数 。
  8. Socket缓冲区大小:TCP连接的性能也受到Socket缓冲区大小的限制,可以通过net.ipv4.tcp_rmemnet.ipv4.tcp_wmem进行调整 。
  9. TIME_WAIT套接字重用:在高并发场景下,允许重用处于TIME_WAIT状态的套接字可以节省资源,可以通过设置net.ipv4.tcp_tw_reuse来实现 。
  10. 系统资源:最终,系统资源(如内存和CPU)也会影响TCP连接的最大数量。

超出限制时的处理方法

  • 客户端
    • 端口耗尽:当客户端的端口耗尽时,它将无法再建立新的连接。可以通过扩展临时端口范围或使用多台客户端来分担连接负载。
    • 负载均衡:使用负载均衡器将连接分发到多个服务器,减少单一服务器的压力。
  • 服务器
    • 文件描述符限制:如果服务器的文件描述符限制达到了上限,新的连接请求将被拒绝。可以增加文件描述符限制或分布式处理连接。
    • 内存不足:内存不足时,可能会导致系统变慢或崩溃。可以增加物理内存,或优化应用程序的内存使用。
    • 连接重用:通过启用连接重用和TIME_WAIT状态的优化,可以减少对可用端口和连接数量的需求。
    • 缩短TIME_WAIT持续时间:通过调整tcp_fin_timeouttcp_tw_reuse,可以减少TIME_WAIT状态的持续时间和对资源的占用。

# 2.2 HTTP VS HTTPS

HTTP 全称是 HyperText Transfer Protocal,即:超文本传输协议。是互联网上应用最为广泛的一种网络通信协议,它允许将超文本标记语言(HTML)文档从 Web 服务器传送到客户端的浏览器。目前我们使用的是HTTP/1.1 版本。所有的 WWW 文件都必须遵守这个标准。设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。1960 年美国人 Ted Nelson 构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。

HTTP 是个应用层协议。HTTP 无需操心网络通信的具体细节,而是把这些细节都交给了通用可靠的因特网传输协议 TCP/IP。

在 HTTP 客户端向服务器发送报文之前,需要用网络协议(Internet Protocol,IP)地址和端口号在客户端和服务器之间建立一条 TCP/IP 协议。而 IP 地址就是通过 URL 提供的,像 http://207.200.21.11:80/index.html,还有使用域名服务(Domain Name Services,DNS)的 http://www.starfish.ink

img

# 协议版本之间的区别?

  • HTTP/0.9

    HTTP协议的最初版本,功能简陋

    • 特点

      • 仅支持 GET 方法。

      • 仅支持简单的 HTML 文本传输,不支持图片、CSS、JS 等内容。

      • 无状态,无请求头和响应头。

    • 用途:非常基础,主要用于早期的超文本传输。

  • HTTP/1.0

    • 新增功能

      • 支持更多请求方法:GET、POST、HEAD。
      • 支持请求头和响应头,允许传递元信息(如编码、内容类型等)。
      • 支持非 HTML 类型文件传输(如图片、视频)。
      • 每次请求建立一个新的 TCP 连接(无连接复用)。
    • 缺点

      • 1.0版本的工作方式是每次TCP连接只能发送一个请求,当服务器响应后就会关闭这次连接,下一个请求需要再次建立TCP连接,就是不支持keepalive。每次请求都需要新建和关闭 TCP 连接,导致性能低下。
  • HTTP/1.0+

    在 20 世纪 90 年代中叶,为满足飞快发展的万维网,很多流行的 Web 客户端和服务器飞快的向 HTTP 中添加各种特性,包括持久的 keep-alive 连接、虚拟主机支持,以及代理连接支持都被加入到 HTTP 中,并称为非官方的事实标准。这种非正式的 HTTP 扩展版本通常称为 HTTP/1.0+

  • HTTP/1.1

    http1.1是目前最为主流的http协议版本,从1997年发布至今,仍是主流的http协议版本。

    • 改进点

      1. 引入了持久连接,或叫长连接( persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive
      2. 分块传输编码(Chunked Encoding):支持动态内容的传输,服务器可以分块发送数据,不需要知道整体数据长度。
      3. 增加新方法:增加 PUT、DELETE、OPTIONS 等方法,增强了 RESTful 风格接口支持。
      4. 缓存机制增强:引入了更复杂的缓存控制(如 Cache-ControlETag)。
      5. 引入了管道机制( pipelining),即在同一个TCP连接里,客户端可以同时发送多个请求,进一步改进了HTTP协议的效率
    • 缺点

      • 受限于 TCP 的阻塞问题(即“队头阻塞”)。
  • HTTP/2.0(又名 HTTP-NG)

    http/2 发布于 2015 年,目前应用还比较少。

    • 改进点
      1. 二进制帧传输:http/2是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧,提升传输效率和解析速度。
      2. 多路复用(Multiplexing):同一个 TCP 连接中可以同时处理多个请求,不会相互阻塞。
      3. Header 压缩:通过 HPACK 算法对请求头和响应头进行压缩,减少传输大小。
      4. 服务器推送(Server Push):服务器可以主动推送资源(如 CSS、JS 文件),减少客户端请求等待时间。
    • 缺点
      • 仍然依赖 TCP 协议,队头阻塞的问题未完全解决。
  • HTTP/3

    • 改进点:

      1. 基于 QUIC 协议:使用 UDP 代替 TCP,解决了队头阻塞问题。
      2. 连接迁移:支持连接迁移功能(如在网络切换时,无需重新建立连接)。
      3. 更低的延迟:减少了连接建立时的握手延迟。
    • 优势:更高效的传输性能,适合现代化的应用需求。

# HTTP/3 了解吗?

HTTP/2 存在的问题

我们知道,传统 Web 平台的数据传输都基于 TCP 协议,而 TCP 协议在创建连接之前不可避免的需要三次握手,如果需要提高数据交互的安全性,即增加传输层安全协议(TLS),还会增加更多的握手次数。 HTTP 从 1.0 到 2.0,其传输层都是基于 TCP 协议的。即使是带来巨大性能提升的 HTTP/2,也无法完全解决 TCP 协议存在的固有问题(慢启动,拥塞窗口尺寸的设置等)。此外,HTTP/2 多路复用只是减少了连接数,其队头的拥塞问题并没有完全解决,倘若 TCP 丢包率过大,则 HTTP/2 的表现将不如 HTTP/1.1。

QUIC 协议

QUIC(Quick UDP Internet Connections),直译为快速 UDP 网络连接,是谷歌制定的一种基于 UDP 的低延迟传输协议。其主要目的是解决采用传输层 TCP 协议存在的问题,同时满足传输层和应用层对多连接、低延迟等的需求。该协议融合了 TCP, TLS, HTTP/2 等协议的特性,并基于 UDP传输。该协议带来的主要提升有:

低延迟连接。当客户端第一次连接服务器时,QUIC 只需要 1 RTT(Round-Trid Time)延迟就可以建立安全可靠的连接(采用 TLS 1.3 版本),相比于 TCP + TLS 的 3 次 RTT 要更加快捷。之后,客户端可以在本地缓存加密的认证信息,当再次与服务器建立连接时可以实现 0 RTT 的连接建立延迟。

QUIC 复用了 HTTP/2 协议的多路复用功能,由于 QUIC 基于 UDP,所以也避免了 HTTP/2存在的队头阻塞问题。

基于 UDP 协议的 QUIC 运行在用户域而不是系统内核,这使得 QUIC 协议可以快速的更新和部署,从而很好地解决了 TPC 协议部署及更新的困难。

QUIC 的报文是经过加密和认证的,除了少量的报文,其它所有的 QUIC 报文头部都经过了认证,报文主体经过了加密。只要有攻击者篡改 QUIC 报文,接收端都能及时发现。

具有向前纠错机制,每个数据包携带了除了本身内容外的部分其他数据包的内容,使得在出现少量丢包的情况下,尽量地减少其它包的重传次数,其通过牺牲单个包所携带的有效数据大小换来更少的重传次数,这在丢包数量较小的场景下能够带来一定程度的性能提升。

HTTP/3

HTTP/3 是在 QUIC 基础上发展起来的,其底层使用 UDP 进行数据传输,上层仍然使用 HTTP/2。在 UDP 与 HTTP/2 之间存在一个 QUIC 层,其中 TLS 加密过程在该层进行处理。HTTP/3 主要有以下几个特点:

  1. 使用 UDP 作为传输层进行通信;
  2. 在 UDP 之上的 QUIC 协议保证了 HTTP/3 的安全性。QUIC 在建立连接的过程中就完成了 TLS 加密握手;
  3. 建立连接快,正常只需要 1 RTT 即可建立连接。如果有缓存之前的会话信息,则直接验证和建立连接,此过程 0 RTT。建立连接时,也可以带有少量业务数据;
  4. 不和具体底层连接绑定,QUIC 为每个连接的两端分别分配了一个唯一 ID,上层连接只认这对逻辑 ID。网络切换或者断连时,只需要继续发送数据包即可完成连接的建立;
  5. 使用 QPACK 进行头部压缩,因为 在 HTTP/2 中的 HPACK 要求传输过程有序,这会导致队头阻塞,而 QPACK 不存在这个问题。

最后我们使用一张图来清晰的表示出 HTTP 协议的发展变化: img

# URI 和 URL 区别?

URI(Uniform Resource Identifier,统一资源标识符)和 URL(Uniform Resource Locator,统一资源定位符)是网络中用于标识资源的术语

每个Web 服务器资源都有一个名字,这样客户端就可以说明他们感兴趣的资源是什么了,服务器资源名被称为统一资源标识符(URI)。URI 就像因特网上的邮政地址一样,在世界范围内唯一标识并定位信息资源。

统一资源定位符(URL)是资源标识符最常见的形式。 URL 描述了一台特定服务器上某资源的特定位置。

现在几乎所有的 URI 都是 URL。

URI 的第二种形式就是统一资源名(URN)。URN 是作为特定内容的唯一名称使用的,与目前的资源所在地无关。

# HTTP消息的结构

事务和报文

客户端是怎样通过 HTTP 与 Web 服务器及其资源进行事务处理的呢?一个 HTTP 事务由一条请求命令(从客户端发往服务器)和一个响应(从服务器发回客户端)结果组成。这种通信是通过名为HTTP报文(HTTP Message)的格式化数据块进行的。

img

HTTP 报文是纯文本,不是二进制代码。从 Web 客户端发往 Web 服务器的 HTTP 报文称为请求报文(request message)。从服务器发往客户端的报文称为响应报文。

img

HTTP 报文包括三部分:

  • 起始行
  • 首部字段
  • 主体
# 常见HTTP 首部字段:

a、通用首部字段(请求报文与响应报文都会使用的首部字段)

img

b、请求首部字段(请求报文会使用的首部字段)

img

**c、响应首部字段(**响应报文会使用的首部字段)

img

d、实体首部字段(请求报文与响应报文的的实体部分使用的首部字段)

img

HTTP请求结构: 请求方式 + 请求URI + 协议及其版本

HTTP响应结构: 状态码 + 原因短语 + 协议及其版本

# Keep-Alive 和非 Keep-Alive 区别,对服务器性能有影响吗

在早期的 HTTP/1.0 中,浏览器每次 发起 HTTP 请求都要与服务器创建一个新的 TCP 连接,服务器完成请求处理后立即断开 TCP 连接,服务器不跟踪每个客户也不记录过去的请求。然而创建和关闭连接的过程需要消耗资源和时间,为了减少资源消耗,缩短响应时间,就需要重用连接。在 HTTP/1.1 版本中默认使用持久连接,在此之前的 HTTP 版本的默认连接都是使用非持久连接,如果想要在旧版本的 HTTP 协议上维持持久连接,则需要指定 connection 的首部字段的值为 Keep-Alive 来告诉对方这个请求响应完成后不要关闭,下一次咱们还用这个请求继续交流,我们用一个示意图来更加生动的表示两者的区别:

img

对于非 Keep=Alive 来说,必须为每一个请求的对象建立和维护一个全新的连接。对于每一个这样的连接,客户机和服务器都要分配 TCP 的缓冲区和变量,这给服务器带来的严重的负担,因为一台 Web 服务器可能同时服务于数以百计的客户机请求。在 Keep-Alive 方式下,服务器在响应后保持该 TCP 连接打开,在同一个客户机与服务器之间的后续请求和响应报文可通过相同的连接进行传送。甚至位于同一台服务器的多个 Web 页面在从该服务器发送给同一个客户机时,可以在单个持久 TCP 连接上进行。

然而,Keep-Alive 并不是没有缺点的,当长时间的保持 TCP 连接时容易导致系统资源被无效占用,若对 Keep-Alive 模式配置不当,将有可能比非 Keep-Alive 模式带来的损失更大。因此,我们需要正确地设置 keep-alive timeout 参数,当 TCP 连接在传送完最后一个 HTTP 响应,该连接会保持 keepalive_timeout 秒,之后就开始关闭这个链接。

# GET与POST的区别?

HTTP/1.0 定义了三种请求方法:GET, POST 和 HEAD 方法。

HTTP/1.1 增加了六种请求方法:OPTIONS, PUT, PATCH, DELETE, TRACE 和 CONNECT 方法。

GET与POST是我们常用的两种HTTP Method,二者之间的区别主要包括如下五个方面:

  1. 从功能上讲,GET一般用来从服务器上获取资源,POST一般用来更新服务器上的资源;
  2. 从REST服务角度上说,GET是幂等的,即读取同一个资源,总是得到相同的数据,而POST不是幂等的,因为每次请求对资源的改变并不是相同的;进一步地,GET不会改变服务器上的资源,而POST会对服务器资源进行改变;
  3. 从请求参数形式上看,GET请求的数据会附在URL之后,即将请求数据放置在HTTP报文的请求头中,以 ? 分割URL和传输数据,参数之间以 & 相连。特别地,如果数据是英文字母/数字,原样发送;否则,会将其编码为 application/x-www-form-urlencoded MIME 字符串(如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII);而POST请求会把提交的数据则放置在是HTTP请求报文的 请求体 中。
  4. 就安全性而言,POST的安全性要比GET的安全性高,因为GET请求提交的数据将明文出现在URL上,而且POST请求参数则被包装到请求体中,相对更安全。
  5. 从请求的大小看,GET请求的长度受限于浏览器或服务器对URL长度的限制,允许发送的数据量比较小,而POST请求则是没有大小限制的。

# GET 的长度限制是多少?

HTTP 中的 GET 方法是通过 URL 传递数据的,而 URL 本身并没有对数据的长度进行限制,真正限制 GET 长度的是浏览器,例如 IE 浏览器对 URL 的最大限制为 2000多个字符,大概 2KB左右,像 Chrome, FireFox 等浏览器能支持的 URL 字符数更多,其中 FireFox 中 URL 最大长度限制为 65536 个字符,Chrome 浏览器中 URL 最大长度限制为 8182 个字符。并且这个长度不是只针对数据部分,而是针对整个 URL 而言,在这之中,不同的服务器同样影响 URL 的最大长度限制。因此对于特定的浏览器,GET的长度限制不同。

由于 POST 方法请求参数在请求主体中,理论上讲,post 方法是没有大小限制的,而真正起限制作用的是服务器处理程序的处理能力。

# 常见的状态码?

之前面试被问到过,206 是什么意思、状态码 301 和 302 的区别?

每条HTTP响应报文返回时都会携带一个状态码。状态码是一个三位数字的代码,告知客户端请求是否成功,或者是都需要采取其他动作。

  • 1xx:表明服务端接收了客户端请求,客户端继续发送请求;
  • 2xx:客户端发送的请求被服务端成功接收并成功进行了处理;
  • 3xx:服务端给客户端返回用于重定向的信息;
  • 4xx:客户端的请求有非法内容;
  • 5xx:服务端未能正常处理客户端的请求而出现意外错误。
  • 200 OK:表示从客户端发送给服务器的请求被正常处理并返回;

  • 204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回)

  • 206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。

  • 301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;

  • 302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;

  • 303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源

  • 304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;

  • 400 Bad Request:表示请求报文中存在语法错误;

  • 401 Unauthorized:未经许可,需要通过 HTTP 认证;

  • 403 Forbidden:服务器拒绝该次访问(访问权限出现问题)

    • 身份验证 vs. 授权:401 表示身份验证问题,即用户未提供凭证或凭证无效。403 表示授权问题,即用户已经提供了凭证,但凭证不足以访问特定资源。
    • 原因:401 通常是因为缺少认证信息,而 403 是因为服务器拒绝了用户的请求,即使认证信息是有效的。
  • 404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;

  • 500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;

  • 502 Bad Gateway:服务器作为网关或代理,从上游服务器收到无效响应。

  • 503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;

# HTTPS

HTTP 缺点:

  1. 通信使用明文不对数据进行加密(内容容易被窃听)
  2. 不验证通信方身份(容易伪装)
  3. 无法确定报文完整性(内容易被篡改)

因此,HTTP 协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。

为了解决 HTTP 协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议 HTTPS,为了数据传输的安全,HTTPS 在 HTTP 的基础上加入了 SSL(安全套接层)协议,SSL 依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。

与 SSL(安全套接层)组合使用的 HTTP 就是 HTTPS

img

img

# HTTP 与 HTTPs 的工作方式【建立连接的过程】

HTTP

HTTP(Hyper Text Transfer Protocol: 超文本传输协议) 是一种简单的请求 - 响应协议,被用于在 Web 浏览器和网站服务器之间传递消息。HTTP 使用 TCP(而不是 UDP)作为它的支撑运输层协议。其默认工作在 TCP 协议 80 端口,HTTP 客户机发起一个与服务器的 TCP 连接,一旦连接建立,浏览器和服务器进程就可以通过套接字接口访问 TCP。客户机从套接字接口发送 HTTP 请求报文和接收 HTTP 响应报文。类似地,服务器也是从套接字接口接收 HTTP 请求报文和发送 HTTP 响应报文。其通信内容以明文的方式发送,不通过任何方式的数据加密。当通信结束时,客户端与服务器关闭连接。

HTTPS

HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer)是以安全为目标的 HTTP 协议,在 HTTP 的基础上通过传输加密和身份认证的方式保证了传输过程的安全性。其工作流程如下:

  1. Client 使用 https 的 URL 访问 Server,要求与 Server 建立 SSL 连接
  2. Server 把事先配置好的公钥证书返回给客户端。
  3. Client 验证公钥证书:比如是否在有效期内,证书的用途是不是匹配 Client 请求的站点,是不是在 CRL 吊销列表里面,它的上一级证书是否有效,这是一个递归的过程,直到验证到根证书(操作系统内置的Root证书或者Client内置的Root证书)。如果验证通过则继续,不通过则显示警告信息。
  4. Client 使用伪随机数生成器生成加密所使用的对称密钥,然后用证书的公钥加密这个对称密钥,发给Server。
  5. Server使用自己的私钥(private key)解密这个消息,得到对称密钥。至此,Client和Server双方都持有了相同的对称密钥。
  6. Server使用对称密钥加密“明文内容A”,发送给Client。
  7. Client使用对称密钥解密响应的密文,得到“明文内容A”。
  8. Client再次发起HTTPS的请求,使用对称密钥加密请求的“明文内容B”,然后Server使用对称密钥解密密文,得到“明文内容B”。

img

# HTTP 和 HTTPS 的区别?

HTTP 协议传输的数据都是未加密的,也就是明文的,因此使用 HTTP 协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了 SSL(Secure Sockets Layer)协议用于对 HTTP 协议传输的数据进行加密,从而就诞生了 HTTPS。简单来说,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 HTTP 协议安全。

  1. HTTP 协议以明文方式发送内容,数据都是未加密的,安全性较差。HTTPS 数据传输过程是加密的,安全性较好。
  2. HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是 80 端口,后者是 443 端口。
  3. HTTPS 协议需要到数字认证机构(Certificate Authority, CA)申请证书,一般需要一定的费用。
  4. HTTP 页面响应比 HTTPS 快,主要因为 HTTP 使用 3 次握手建立连接,客户端和服务器需要握手 3 次,而 HTTPS 除了 TCP 的 3 次握手,还需要经历一个 SSL 协商过程。

# 说一下对称加密与非对称加密?

主要的加密方法分为两种:一种是共享密钥加密(对称密钥加密),一种是公开密钥加密(非对称密钥加密)

# 共享密钥加密(对称秘钥加密)

加密与解密使用同一个密钥,常见的对称加密算法:DES,AES,3DES等。

img

也就是说在加密的同时,也会把密钥发送给对方。在发送密钥过程中可能会造成密钥被窃取,那么如何解决这一问题呢?

# 公开密钥(非对称密钥)

公开密钥使用一对非对称密钥。一把叫私有密钥,另一把叫公开密钥。私有密钥不让任何人知道,公有密钥随意发送。公钥加密的信息,只有私钥才能解密。常见的非对称加密算法:RSA,ECC等。

也就是说,发送密文方使用对方的公开密钥进行加密,对方接收到信息后,使用私有密钥进行解密。

img

对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。

非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。

为了解决这一问题,https 采用对称加密与非对称加密的混合加密方式。

# 非对称加密有哪些缺点?

非对称加密在某些方面存在一些缺点,主要包括:

  1. 性能开销:非对称加密通常比对称加密慢,因为它涉及更复杂的数学运算,这使得它在处理大量数据时效率较低。
  2. 加密速度:非对称加密的加密和解密速度通常较慢,这限制了它在需要快速处理的场景中的应用。
  3. 密钥管理:虽然非对称加密的公钥可以公开,但私钥必须严格保密,这增加了密钥管理的复杂性。
  4. 密钥长度:为了确保安全性,非对称加密通常需要较长的密钥长度,这可能导致存储和传输的开销增加。
  5. 资源消耗:非对称加密算法在执行时可能消耗更多的计算资源,这在资源受限的环境中可能是一个问题。
  6. 数字签名:非对称加密常用于数字签名,但如果私钥被泄露,可能会对系统的安全性造成威胁。
  7. 算法限制:某些非对称加密算法可能受到特定的算法限制,例如RSA算法受到素数生成技术的限制。
  8. 适用场景限制:非对称加密通常不适用于需要快速加解密的场景,如实时通信或大量数据的加密存储。

# HTTPS加密过程概述?

最开始还是TCP三次握手,之后,HTTPS需要进行TLS握手以建立安全连接

  1. 客户端发起HTTPS请求
    • 用户在浏览器中输入网址(如https://www.example.com),浏览器会向服务器发起HTTPS请求。
  2. 服务器响应并发送证书
    • 服务器接收到客户端请求后,向客户端发送服务器的数字证书。这个证书由受信任的证书颁发机构(CA)签发,包含服务器的公钥和其他信息。
  3. 客户端验证证书
    • 客户端(浏览器)接收到服务器的数字证书后,会验证证书的有效性,检查证书是否由受信任的CA签发,证书是否在有效期内,证书的域名是否与访问的域名匹配。如果证书验证通过,客户端将继续加密过程;否则,客户端会显示警告,提示用户证书无效。
  4. 生成会话密钥
    • 客户端在验证证书通过后,会生成一个随机的会话密钥(对称密钥),用于加密后续的通信数据。因为对称加密速度快且效率高,所以HTTPS在数据传输阶段使用对称加密。
  5. 加密会话密钥并传输
    • 客户端使用服务器的公钥(从证书中获取)加密生成的会话密钥,然后将加密后的会话密钥发送给服务器。由于非对称加密的特性,只有服务器能够使用其私钥解密这个会话密钥。
  6. 服务器解密会话密钥
    • 服务器使用自己的私钥解密客户端传来的加密会话密钥,得到会话密钥。至此,客户端和服务器都拥有了相同的会话密钥,可以用它来加密和解密后续的通信数据。
  7. 使用对称加密进行数据传输
    • 在整个会话期间,客户端和服务器都使用这个对称会话密钥对数据进行加密和解密。数据在传输过程中即使被拦截,由于使用了对称加密,攻击者无法解密数据。
  8. 会话结束
    • 当通信结束时,客户端和服务器都会丢弃会话密钥。如果需要再进行通信,会重新启动一个新的加密过程。

# SSL/TSL

SSL(Secure Sockets Layer),中文叫做“安全套接层”。它是在上世纪90年代中期,由网景公司设计的。

SSL 协议就是用来解决 HTTP 传输过程的不安全问题,到了1999年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(是“Transport Layer Security”的缩写),中文叫做“传输层安全协议”。

很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。

SSL/TLS协议的基本思路是采用公钥加密法 (opens new window),也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。

但是,这里有两个问题。

  • 如何保证公钥不被篡改?

​ 解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。

  • 公钥加密计算量太大,如何减少耗用的时间?

    每一次对话(session),客户端和服务器端都生成一个"对话密钥"(session key),用它来加密信息。由于"对话密钥"是对称加密,所以运算速度非常快,而服务器公钥只用于加密"对话密钥"本身,这样就减少了加密运算的消耗时间。

因此,SSL/TLS协议的基本过程是这样的:

  1. 服务端将非对称加密的公钥发送给客户端;

  2. 客户端拿着服务端发来的公钥,对对称加密的key做加密并发给服务端;

  3. 服务端拿着自己的私钥对发来的密文解密,从而获取到对称加密的key;

  4. 二者利用对称加密的key对需要传输的消息做加解密传输。

HTTPS 相比 HTTP,在请求前多了一个「握手」的环节。

握手过程中确定了数据加密的密码。在握手过程中,网站会向浏览器发送 SSL 证书,SSL 证书和我们日常用的身份证类似,是一个支持 HTTPS 网站的身份证明,SSL 证书里面包含了网站的域名,证书有效期,证书的颁发机构以及用于加密传输密码的公钥等信息,由于公钥加密的密码只能被在申请证书时生成的私钥解密,因此浏览器在生成密码之前需要先核对当前访问的域名与证书上绑定的域名是否一致,同时还要对证书的颁发机构进行验证,如果验证失败浏览器会给出证书错误的提示。

# 证书

img

实际上,我们使用的证书分很多种类型,SSL证书只是其中的一种。证书的格式是由 X.509 标准定义。SSL 证书负责传输公钥,是一种PKI(Public Key Infrastructure,公钥基础结构)证书。

我们常见的证书根据用途不同大致有以下几种:

  1. SSL证书,用于加密HTTP协议,也就是HTTPS。
  2. 代码签名证书,用于签名二进制文件,比如Windows内核驱动,Firefox插件,Java代码签名等等。
  3. 客户端证书,用于加密邮件。
  4. 双因素证书,网银专业版使用的USB Key里面用的就是这种类型的证书。

这些证书都是由受认证的证书颁发机构——我们称之为CA(Certificate Authority)机构来颁发,针对企业与个人的不同,可申请的证书的类型也不同,价格也不同。CA机构颁发的证书都是受信任的证书,对于 SSL 证书来说,如果访问的网站与证书绑定的网站一致就可以通过浏览器的验证而不会提示错误。

# 客户端为什么信任第三方证书

假设中间人篡改了证书原文,由于他没有 CA 机构的私钥,所以无法得到此时加密后的签名,因此无法篡改签名。客户端浏览器收到该证书后会发现原文和签名解密后的值不一致,则说明证书被中间人篡改,证书不可信,从而终止向服务器传输信息。

上述过程说明证书无法被篡改,我们考虑更严重的情况,例如中间人拿到了 CA 机构认证的证书,它想窃取网站 A 发送给客户端的信息,于是它成为中间人拦截到了 A 传给客户端的证书,然后将其替换为自己的证书。此时客户端浏览器收到的是被中间人掉包后的证书,但由于证书里包含了客户端请求的网站信息,因此客户端浏览器只需要把证书里的域名与自己请求的域名比对一下就知道证书有没有被掉包了。

# HTTPS的优缺点

尽管 HTTPS 并非绝对安全,掌握根证书的机构、掌握加密算法的组织同样可以进行中间人形式的攻击,但 HTTPS仍是现行架构下最安全的解决方案,主要有以下几个好处:

  1. 使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;
  2. HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。
  3. HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。
  4. 谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。

HTTPS的缺点

虽然说HTTPS有很大的优势,但其相对来说,还是存在不足之处的:

  1. HTTPS协议握手阶段比较费时,会使页面的加载时间延长近50%,增加10%到20%的耗电;
  2. HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;
  3. SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。
  4. SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。
  5. HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。

# HTTP 切换到 HTTPS

  1. 通过获取 SSL/TLS 证书
  2. 配置 Web 服务器:不同的 Web 服务器(如 Nginx、Apache)配置方式不同
  3. 重定向 HTTP 到 HTTPS、
  4. 更新应用配置和链接
    • 更新应用配置:如果你的应用中有硬编码的 HTTP 链接,确保将它们更新为 HTTPS
    • 更新静态资源链接:确保所有静态资源(如图片、CSS、JS 文件)的链接使用 HTTPS
  5. 配置 HSTS:HSTS 强制客户端(如浏览器)使用 HTTPS 访问你的站点,进一步提高安全性
  6. 进行测试和验证

# 三、网络安全

# 安全攻击有哪些

网络安全攻击主要分为被动攻击和主动攻击两类:

  • 被动攻击:攻击者窃听和监听数据传输,从而获取到传输的数据信息,被动攻击主要有两种形式:消息内容泄露攻击和流量分析攻击。由于攻击者并没有修改数据,使得这种攻击类型是很难被检测到的。
  • 主动攻击:攻击者修改传输的数据流或者故意添加错误的数据流,例如假冒用户身份从而得到一些权限,进行权限攻击,除此之外,还有重放、改写和拒绝服务等主动攻击的方式。

# ARP 攻击

在 ARP 的解析过程中,局域网上的任何一台主机如果接收到一个 ARP 应答报文,并不会去检测这个报文的真实性,而是直接记入自己的 ARP 缓存表中。并且这个 ARP 表是可以被更改的,当表中的某一列长时间不适使用,就会被删除。ARP 攻击就是利用了这一点,攻击者疯狂发送 ARP 报文,其源 MAC 地址为攻击者的 MAC 地址,而源 IP 地址为被攻击者的 IP 地址。通过不断发送这些伪造的 ARP 报文,让网络内部的所有主机和网关的 ARP 表中被攻击者的 IP 地址所对应的 MAC 地址为攻击者的 MAC 地址。这样所有发送给被攻击者的信息都会发送到攻击者的主机上,从而产生 ARP 欺骗。通常可以把 ARP 欺骗分为以下几种:

  • 洪泛攻击

    攻击者恶意向局域网中的网关、路由器和交换机等发送大量 ARP 报文,设备的 CPU 忙于处理 ARP 协议,而导致难以响应正常的服务请求。其表现通常为:网络中断或者网速很慢。

  • 欺骗主机

    这种攻击方式也叫仿冒网关攻击。攻击者通过 ARP 欺骗使得网络内部被攻击主机发送给网关的信息实际上都发送给了攻击者,主机更新的 ARP 表中对应的 MAC 地址为攻击者的 MAC。当用户主机向网关发送重要信息使,该攻击方式使得用户的数据存在被窃取的风险。

  • 欺骗网关

    该攻击方式和欺骗主机的攻击方式类似,不过这种攻击的欺骗对象是局域网的网关,当局域网中的主机向网关发送数据时,网关会把数据发送给攻击者,这样攻击者就会源源不断地获得局域网中用户的信息。该攻击方式同样会造成用户数据外泄。

  • 中间人攻击:攻击者同时欺骗网关和主机,局域网的网关和主机发送的数据最后都会到达攻击者这边。这样,网关和用户的数据就会泄露。

  • IP 地址冲突:攻击者对局域网中的主机进行扫描,然后根据物理主机的 MAC 地址进行攻击,导致局域网内的主机产生 IP 冲突,使得用户的网络无法正常使用。

# AES 的过程

AES(Advanced Encryption Standard)即密码学的高级加密标准,也叫做 Rijndeal 加密法,是最为常见的一种对称加密算法,和传统的对称加密算法大致的流程类似,在发送端需要采用加密算法对明文进行加密,在接收端需要采用与加密算法相同的算法进行解密,不同的是, AES 采用分组加密的方式,将明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在 AES 标准中,分组长度固定为 128 位,即每个分组为 16 个字节(每个字节有 8 位)。而密钥的长度可以是 128 位,192 位或者 256 位。并且密钥的长度不同,推荐加密的轮数也不同。

我们以 128 位密钥为例(加密轮次为 10),已知明文首先需要分组,每一组大小为16个字节并形成 4 × 4 的状态矩阵(矩阵中的每一个元素代表一个字节)。类似地,128 位密钥同样用 4 × 4 的字节矩阵表示,矩阵中的每一列称为 1 个 32 位的比特字。通过密钥编排函数该密钥矩阵被扩展成一个由 44 个字组成的序列,该序列的前四个字是原始密钥,用于 AES 的初始密钥加过程,后面 40 个字分为 10 组,每组 4 个字分别用于 10 轮加密运算中的轮密钥加。在每轮加密过程中主要包括四个步骤:

字节代换:AES 的字节代换其实是一个简易的查表操作,在 AES 中定义了一个 S-box 和一个逆 S-box,我们可以将其简单地理解为两个映射表,在做字节代换时,状态矩阵中的每一个元素(字节)的高四位作为行值,低四位作为列值,取出 S-box 或者逆 S-box 中对应的行或者列作为输出。

行位移:顾名思义,就是对状态矩阵的每一行进行位移操作,其中状态矩阵的第 0 行左移 0 位,第 1 行左移 1 位,以此类推。

列混合:列混合变换是通过矩阵相乘来实现的,经唯一后的状态矩阵与固定的矩阵相乘,从而得到混淆后的状态矩阵。其中矩阵相乘中涉及到的加法等价于两个字节的异或运算,而乘法相对复杂一些,对于状态矩阵中的每一个 8 位二进制数来说,首先将其与 00000010 相乘,其等效为将 8 位二进制数左移一位,若原二进制数的最高位是 1 的话再将左移后的数与 00011011 进行异或运算。

轮密相加:在开始时我们提到,128 位密钥通过密钥编排函数被扩展成 44 个字组成的序列,其中前 4 个字用于加密过程开始时对原始明文矩阵进行异或运算,而后 40 个字中每四个一组在每一轮中与状态矩阵进行异或运算(共计 10 轮)。

上述过程即为 AES 加密算法的主要流程,在我们的例子中,上述过程需要经过 10 轮迭代。而 AES 的解密过程的各个步骤和加密过程是一样的,只是用逆变换取代原来的变换。

# RSA 和 AES 算法有什么区别

  • RSA:采用非对称加密的方式,采用公钥进行加密,私钥解密的形式。其私钥长度一般较长,除此之外,由于需要大数的乘幂求模等运算,其运算速度较慢,不适合大量数据文件加密。

  • AES:采用对称加密的方式,其密钥长度最长只有 256 个比特,加密和解密速度较快,易于硬件实现。由于是对称加密,通信双方在进行数据传输前需要获知加密密钥。

基于上述两种算法的特点,一般使用 RSA 传输密钥给对方,之后使用 AES 进行加密通信。

# DDoS 有哪些,如何防范

DDoS 为分布式拒绝服务攻击,是指处于不同位置的多个攻击者同时向一个或数个目标发动攻击,或者一个攻击者控制了不同位置上的多台机器并利用这些机器对受害者同时实施攻击。和单一的 DoS 攻击相比,DDoS 是借助数百台或者数千台已被入侵并添加了攻击进程的主机一起发起网络攻击。

DDoS 攻击主要有两种形式:流量攻击和资源耗尽攻击。前者主要针对网络带宽,攻击者和已受害主机同时发起大量攻击导致网络带宽被阻塞,从而淹没合法的网络数据包;后者主要针对服务器进行攻击,大量的攻击包会使得服务器资源耗尽或者 CPU 被内核应用程序占满从而无法提供网络服务。

常见的 DDos 攻击主要有:TCP 洪水攻击(SYN Flood)、放射性攻击(DrDos)、CC 攻击(HTTP Flood)等。

针对 DDoS 中的流量攻击,最直接的方法是增加带宽,理论上只要带宽大于攻击流量就可以了,但是这种方法成本非常高。在有充足网络带宽的前提下,我们应尽量提升路由器、网卡、交换机等硬件设施的配置。

针对资源耗尽攻击,我们可以升级主机服务器硬件,在网络带宽得到保证的前提下,使得服务器能有效对抗海量的 SYN 攻击包。我们也可以安装专业的抗 DDoS 防火墙,从而对抗 SYN Flood等流量型攻击。此外,负载均衡,CDN 等技术都能够有效对抗 DDoS 攻击

# 四、Other FAQ

# 从输入网址到获得页面的过程

  1. 浏览器查询 DNS,获取域名对应的 IP 地址:具体过程包括浏览器搜索自身的DNS缓存、搜索操作系统的DNS缓存、读取本地的Host文件和向本地DNS服务器进行查询等。对于向本地DNS服务器进行查询,如果要查询的域名包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析(此解析具有权威性);如果要查询的域名不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析(此解析不具有权威性)。如果本地域名服务器并未缓存该网址映射关系,那么将根据其设置发起递归查询或者迭代查询;
  2. 浏览器获得域名对应的 IP 地址以后,浏览器向服务器请求建立链接,发起三次握手;
  3. TCP/IP 链接建立起来后,浏览器向服务器发送 HTTP 请求;
  4. 服务器接收到这个请求,并根据路径参数映射到特定的请求处理器进行处理,并将处理结果及相应的视图返回给浏览器;
  5. 浏览器解析并渲染视图,若遇到对js文件、css文件及图片等静态资源的引用,则重复上述步骤并向服务器请求这些资源;
  6. 浏览器根据其请求到的资源、数据渲染页面,最终向用户呈现一个完整的页面。

简单版

  1. DNS解析
  2. TCP连接
  3. 发送HTTP请求
  4. 服务器处理请求并返回HTTP报文
  5. 浏览器解析渲染页面
  6. 连接结束

img

# 如果你访问一个网站很慢,怎么排查和解决

网页打开速度慢的原因有很多,这里列举出一些较常出现的问题:

① 首先最直接的方法是查看本地网络是否正常,可以通过网络测速软件例如电脑管家等对电脑进行测速,若网速正常,我们查看网络带宽是否被占用,例如当你正在下载电影时并且没有限速,是会影响你打开网页的速度的,这种情况往往是处理器内存小导致的;

② 当网速测试正常时,我们对网站服务器速度进行排查,通过 ping 命令查看链接到服务器的时间和丢包等情况,一个速度好的机房,首先丢包率不能超过 1%,其次 ping 值要小,最后是 ping 值要稳定,如最大和最小差值过大说明路由不稳定。或者我们也可以查看同台服务器上其他网站的打开速度,看是否其他网站打开也慢。

③ 如果网页打开的速度时快时慢,甚至有时候打不开,有可能是空间不稳定的原因。当确定是该问题时,就要找你的空间商解决或换空间商了,如果购买空间的话,可选择购买购买双线空间或多线空间;如果是在有的地方打开速度快,有的地方打开速度慢,那应该是网络线路的问题。电信线路用户访问放在联通服务器的网站,联通线路用户访问放在电信服务器上的网站,相对来说打开速度肯定是比较慢。

④ 从网站本身找原因。网站的问题主要包括网站程序设计、网页设计结构和网页内容三个部分。

  • 网站程序设计:当访问网页中有拖慢网站打开速度的代码,会影响网页的打开速度,例如网页中的统计代码,我们最好将其放在网站的末尾。因此我们需要查看网页程序的设计结构是否合理;
  • 网页设计结构:如果是 table 布局的网站,查看是否嵌套次数太多,或是一个大表格分成多个表格这样的网页布局,此时我们可以采用 div 布局并配合 css 进行优化。
  • 网页内容:查看网页中是否有许多尺寸大的图片或者尺寸大的 flash 存在,我们可以通过降低图片质量,减小图片尺寸,少用大型 flash 加以解决。此外,有的网页可能过多地引用了其他网站的内容,若某些被引用的网站访问速度慢,或者一些页面已经不存在了,打开的速度也会变慢。一种直接的解决方法是去除不必要的加载项。

# XSS 攻击

XSS 攻击(Cross-Site Scripting,跨站脚本攻击)是一种常见的网络安全攻击,攻击者通过在网站的输入字段中注入恶意脚本,当其他用户访问该网站时,恶意脚本会在他们的浏览器中执行,从而窃取敏感信息、篡改页面内容或进行其他恶意操作。

XSS 攻击可以分为三种类型:

  1. 存储型 XSS
    • 攻击者的脚本被存储在目标服务器上,通常是在数据库中。
    • 当其他用户访问受感染的页面时,恶意脚本作为正常内容的一部分被发送到用户的浏览器中执行。
  2. 反射型 XSS
    • 攻击者的脚本不是存储在服务器上,而是在用户访问特定页面或请求时,通过 URL 参数或其他方式传递给服务器。
    • 服务器将恶意脚本作为响应的一部分发送回用户的浏览器,如果浏览器解析并执行了这些脚本,就构成了攻击。
  3. DOM 型 XSS
    • 这种类型的 XSS 攻击与服务器无关,恶意脚本完全在客户端执行。
    • 攻击者利用浏览器的 DOM 解析特性,通过修改页面的 DOM 来注入恶意脚本。

防御 XSS 攻击的策略:

  1. 输入验证:对所有用户输入进行严格的验证,确保不接受潜在的恶意代码。
  2. 输出编码:在将数据发送到浏览器之前,对所有输出进行适当的编码,以确保潜在的脚本被安全地呈现。
  3. 内容安全策略(CSP):使用内容安全策略来限制可以执行的脚本的来源,减少 XSS 攻击的风险。
  4. HTTP 头:设置适当的 HTTP 头,如 X-XSS-Protection,以启用浏览器的 XSS 过滤功能。

# IP地址的分类

IP 地址是指互联网协议地址,是 IP 协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。IP地址编址方案将IP地址空间划分为A、B、C、D、E五类,其中A、B、C是基本类,D、E类作为多播和保留使用,为特殊地址。

每个IP地址包括两个标识码(ID),即网络ID和主机ID。同一个物理网络上的所有主机都使用同一个网络ID,网络上的一个主机(包括网络上工作站,服务器和路由器等)有一个主机ID与其对应。A~E类地址的特点如下:

A类地址:以0开头,第一个字节范围:0~127;

B类地址:以10开头,第一个字节范围:128~191;

C类地址:以110开头,第一个字节范围:192~223;

D类地址:以1110开头,第一个字节范围为224~239;

E类地址:以1111开头,保留地址

img

# HTTP 是不保存状态的协议,如何保存用户状态

我们知道,假如某个特定的客户机在短时间内两次请求同一个对象,服务器并不会因为刚刚为该用户提供了该对象就不再做出反应,而是重新发送该对象,就像该服务器已经完全忘记不久之前所做过的事一样。因为一个 HTTP 服务器并不保存关于客户机的任何信息,所以我们说 HTTP 是一个无状态协议。

通常有两种解决方案:

① 基于 Session 实现的会话保持

在客户端第一次向服务器发送 HTTP 请求后,服务器会创建一个 Session 对象并将客户端的身份信息以键值对的形式存储下来,然后分配一个会话标识(SessionId)给客户端,这个会话标识一般保存在客户端 Cookie 中,之后每次该浏览器发送 HTTP 请求都会带上 Cookie 中的 SessionId 到服务器,服务器根据会话标识就可以将之前的状态信息与会话联系起来,从而实现会话保持。

优点:安全性高,因为状态信息保存在服务器端。

缺点:由于大型网站往往采用的是分布式服务器,浏览器发送的 HTTP 请求一般要先通过负载均衡器才能到达具体的后台服务器,倘若同一个浏览器两次 HTTP 请求分别落在不同的服务器上时,基于 Session 的方法就不能实现会话保持了。

【解决方法:采用中间件,例如 Redis,我们通过将 Session 的信息存储在 Redis 中,使得每个服务器都可以访问到之前的状态信息】

② 基于 Cookie 实现的会话保持

当服务器发送响应消息时,在 HTTP 响应头中设置 Set-Cookie 字段,用来存储客户端的状态信息。客户端解析出 HTTP 响应头中的字段信息,并根据其生命周期创建不同的 Cookie,这样一来每次浏览器发送 HTTP 请求的时候都会带上 Cookie 字段,从而实现状态保持。基于 Cookie 的会话保持与基于 Session 实现的会话保持最主要的区别是前者完全将会话状态信息存储在浏览器 Cookie 中。

优点:服务器不用保存状态信息, 减轻服务器存储压力,同时便于服务端做水平拓展。

缺点:该方式不够安全,因为状态信息存储在客户端,这意味着不能在会话中保存机密数据。除此之外,浏览器每次发起 HTTP 请求时都需要发送额外的 Cookie 到服务器端,会占用更多带宽。

拓展:Cookie被禁用了怎么办?

若遇到 Cookie 被禁用的情况,则可以通过重写 URL 的方式将会话标识放在 URL 的参数里,也可以实现会话保持。

# 什么是Cookie,Cookie的使用过程是怎么样的?

由于 http 协议是无状态协议,如果客户通过浏览器访问 web 应用时没有一个保存用户访问状态的机制,那么将不能持续跟踪应用的操作。比如当用户往购物车中添加了商品,web 应用必须在用户浏览别的商品的时候仍保存购物车的状态,以便用户继续往购物车中添加商品。

cookie 是浏览器的一种缓存机制,它可用于维持客户端与服务器端之间的会话。由于下面一题会讲到 session,所以这里要强调cookie会将会话保存在客户端(session则是把会话保存在服务端)

这里以最常见的登陆案例讲解cookie的使用过程:

  1. 首先用户在客户端浏览器向服务器发起登陆请求
  2. 登陆成功后,服务端会把登陆的用户信息设置 cookie 中,返回给客户端浏览器
  3. 客户端浏览器接收到 cookie 请求后,会把 cookie 保存到本地(可能是内存,也可能是磁盘,看具体使用情况而定)
  4. 以后再次访问该 web 应用时,客户端浏览器就会把本地的 cookie 带上,这样服务端就能根据 cookie 获得用户信息了

# 什么是session,有哪些实现session的机制?

session 是一种维持客户端与服务器端会话的机制。但是与 cookie 把会话信息保存在客户端本地不一样,session 把会话保留在浏览器端。

我们同样以登陆案例为例子讲解 session 的使用过程:

  1. 首先用户在客户端浏览器发起登陆请求
  2. 登陆成功后,服务端会把用户信息保存在服务端,并返回一个唯一的 session 标识给客户端浏览器。
  3. 客户端浏览器会把这个唯一的 session 标识保存在起来
  4. 以后再次访问 web 应用时,客户端浏览器会把这个唯一的 session 标识带上,这样服务端就能根据这个唯一标识找到用户信息。

看到这里可能会引起疑问:把唯一的 session 标识返回给客户端浏览器,然后保存起来,以后访问时带上,这难道不是 cookie 吗?

没错,session 只是一种会话机制,在许多 web 应用中,session 机制就是通过 cookie 来实现的。也就是说它只是使用了 cookie 的功能,并不是使用 cookie 完成会话保存。与 cookie 在保存客户端保存会话的机制相反,session 通过 cookie 的功能把会话信息保存到了服务端。

进一步地说,session 是一种维持服务端与客户端之间会话的机制,它可以有不同的实现。以现在比较流行的小程序为例,阐述一个 session 的实现方案:

  1. 首先用户登陆后,需要把用户登陆信息保存在服务端,这里我们可以采用 redis。比如说给用户生成一个 userToken,然后以 userId 作为键,以 userToken 作为值保存到 redis 中,并在返回时把 userToken 带回给小程序端。
  2. 小程序端接收到 userToken 后把它缓存起来,以后每当访问后端服务时就把 userToken 带上。
  3. 在后续的服务中服务端只要拿着小程序端带来的 userToken 和 redis 中的 userToken 进行比对,就能确定用户的登陆状态了。

# session和cookie有什么区别

经过上面两道题的阐述,这道题就很清晰了

  1. cookie 是浏览器提供的一种缓存机制,它可以用于维持客户端与服务端之间的会话
  2. session 指的是维持客户端与服务端会话的一种机制,它可以通过 cookie 实现,也可以通过别的手段实现。
  3. 如果用 cookie 实现会话,那么会话会保存在客户端浏览器中
  4. 而 session 机制提供的会话是保存在服务端的。

这部分内容对常规后端开发,,,了解点就可以

# 五、了解 | 各层模型应用

# 应用层

# DNS 的作用和原理?

DNS(Domain Name System)是域名系统的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,用于 TCP/IP 网络。

通常我们有两种方式识别主机:通过主机名或者 IP 地址。人们喜欢便于记忆的主机名表示,而路由器则喜欢定长的、有着层次结构的 IP 地址。为了满足这些不同的偏好,我们就需要一种能够进行主机名到 IP 地址转换的目录服务,域名系统作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。

DNS 域名解析原理

DNS 采用了分布式的设计方案,其域名空间采用一种树形的层次结构: img

上图展示了 DNS 服务器的部分层次结构,从上到下依次为根域名服务器、顶级域名服务器和权威域名服务器。其实根域名服务器在因特网上有13个,大部分位于北美洲。第二层为顶级域服务器,这些服务器负责顶级域名(如 com、org、net、edu)和所有国家的顶级域名(如uk、fr、ca 和 jp)。在第三层为权威 DNS 服务器,因特网上具有公共可访问主机(例如 Web 服务器和邮件服务器)的每个组织机构必须提供公共可访问的 DNS 记录,这些记录由组织机构的权威 DNS 服务器负责保存,这些记录将这些主机的名称映射为 IP 地址。

除此之外,还有一类重要的 DNS 服务器,叫做本地 DNS 服务器。本地 DNS 服务器严格来说不在 DNS 服务器的层次结构中,但它对 DNS 层次结构是很重要的。一般来说,每个网络服务提供商(ISP) 都有一台本地 DNS 服务器。当主机与某个 ISP 相连时,该 ISP 提供一台主机的 IP 地址,该主机具有一台或多台其本地 DNS 服务器的 IP 地址。主机的本地 DNS 服务器通常和主机距离较近,当主机发起 DNS 请求时,该请求被发送到本地 DNS 服务器,它起着代理的作用,并将该请求转发到 DNS 服务器层次结构中。

我们以一个例子来了解 DNS 的工作原理,假设主机 A(IP 地址为 abc.xyz.edu) 想知道主机 B 的 IP 地址 (def.mn.edu),如下图所示,主机 A 首先向它的本地 DNS 服务器发送一个 DNS 查询报文。该查询报文含有被转换的主机名 def.mn.edu。本地 DNS 服务器将该报文转发到根 DNS 服务器,根 DNS 服务器注意到查询的 IP 地址前缀为 edu 后向本地 DNS 服务器返回负责 edu 的顶级域名服务器的 IP 地址列表。该本地 DNS 服务器则再次向这些 顶级域名服务器发送查询报文。该顶级域名服务器注意到 mn.edu 的前缀,并用权威域名服务器的 IP 地址进行响应。通常情况下,顶级域名服务器并不总是知道每台主机的权威 DNS 服务器的 IP 地址,而只知道中间的某个服务器,该中间 DNS 服务器依次能找到用于相应主机的 IP 地址,我们假设中间经历了权威服务器 ① 和 ②,最后找到了负责 def.mn.edu 的权威 DNS 服务器 ③,之后,本地 DNS 服务器直接向该服务器发送查询报文从而获得主机 B 的IP 地址。

img

在上图中,IP 地址的查询其实经历了两种查询方式,分别是递归查询和迭代查询。

拓展:域名解析查询的两种方式

递归查询:如果主机所询问的本地域名服务器不知道被查询域名的 IP 地址,那么本地域名服务器就以 DNS 客户端的身份,向其他根域名服务器继续发出查询请求报文,即替主机继续查询,而不是让主机自己进行下一步查询,如上图步骤(1)和(10)。

迭代查询:当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的 IP 地址,要么告诉本地服务器下一步应该找哪个域名服务器进行查询,然后让本地服务器进行后续的查询,如上图步骤(2)~(9)。

# DNS 为什么用 UDP

DNS 既使用 TCP 又使用 UDP。

当进行区域传送(主域名服务器向辅助域名服务器传送变化的那部分数据)时会使用 TCP,因为数据同步传送的数据量比一个请求和应答的数据量要多,而 TCP 允许的报文长度更长,因此为了保证数据的正确性,会使用基于可靠连接的 TCP。

当客户端向 DNS 服务器查询域名 ( 域名解析) 的时候,一般返回的内容不会超过 UDP 报文的最大长度,即 512 字节。用 UDP 传输时,不需要经过 TCP 三次握手的过程,从而大大提高了响应速度,但这要求域名解析器和域名服务器都必须自己处理超时和重传从而保证可靠性。

# 怎么实现 DNS 劫持

DNS 劫持即域名劫持,是通过将原域名对应的 IP 地址进行替换从而使得用户访问到错误的网站或者使得用户无法正常访问网站的一种攻击方式。域名劫持往往只能在特定的网络范围内进行,范围外的 DNS 服务器能够返回正常的 IP 地址。攻击者可以冒充原域名所属机构,通过电子邮件的方式修改组织机构的域名注册信息,或者将域名转让给其它组织,并将新的域名信息保存在所指定的 DNS 服务器中,从而使得用户无法通过对原域名进行解析来访问目的网址。

具体实施步骤如下:

  1. 获取要劫持的域名信息:攻击者首先会访问域名查询站点查询要劫持的域名信息。
  2. 控制域名相应的 E-MAIL 账号:在获取到域名信息后,攻击者通过暴力破解或者专门的方法破解公司注册域名时使用的 E-mail 账号所对应的密码。更高级的攻击者甚至能够直接对 E-mail 进行信息窃取。
  3. 修改注册信息:当攻击者破解了 E-MAIL 后,会利用相关的更改功能修改该域名的注册信息,包括域名拥有者信息,DNS 服务器信息等。
  4. 使用 E-MAIL 收发确认函:在修改完注册信息后,攻击者在 E-mail 真正拥有者之前收到修改域名注册信息的相关确认信息,并回复确认修改文件,待网络公司恢复已成功修改信件后,攻击者便成功完成 DNS 劫持。

用户端的一些预防手段:

直接通过 IP 地址访问网站,避开 DNS 劫持。 由于域名劫持往往只能在特定的网络范围内进行,因此一些高级用户可以通过网络设置让 DNS 指向正常的域名服务器以实现对目的网址的正常访问,例如将计算机首选 DNS 服务器的地址固定为 8.8.8.8。

# socket() 套接字有哪些

套接字(Socket)是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象,网络进程通信的一端就是一个套接字,不同主机上的进程便是通过套接字发送报文来进行通信。例如 TCP 用主机的 IP 地址 + 端口号作为 TCP 连接的端点,这个端点就叫做套接字。

套接字主要有以下三种类型:

  1. 流套接字(SOCK_STREAM):流套接字基于 TCP 传输协议,主要用于提供面向连接、可靠的数据传输服务。由于 TCP 协议的特点,使用流套接字进行通信时能够保证数据无差错、无重复传送,并按顺序接收,通信双方不需要在程序中进行相应的处理。
  2. 数据报套接字(SOCK_DGRAM):和流套接字不同,数据报套接字基于 UDP 传输协议,对应于无连接的 UDP 服务应用。该服务并不能保证数据传输的可靠性,也无法保证对端能够顺序接收到数据。此外,通信两端不需建立长时间的连接关系,当 UDP 客户端发送一个数据给服务器后,其可以通过同一个套接字给另一个服务器发送数据。当用 UDP 套接字时,丢包等问题需要在程序中进行处理。
  3. 原始套接字(SOCK_RAW):由于流套接字和数据报套接字只能读取 TCP 和 UDP 协议的数据,当需要传送非传输层数据包(例如 Ping 命令时用的 ICMP 协议数据包)或者遇到操作系统无法处理的数据包时,此时就需要建立原始套接字来发送。

# REST 和 WebSocket 的区别?

REST(Representational State Transfer)和WebSocket是两种不同的网络通信协议,它们在用途、工作原理和使用场景上有所区别:

  1. 协议类型
    • REST:是一种基于HTTP协议的架构风格,用于网络资源的状态转移和管理系统。
    • WebSocket:是一种网络通信协议,提供了在单个TCP连接上进行全双工通信的能力。
  2. 通信模式
    • REST:通常是基于请求/响应模式,客户端发送请求,服务器响应请求。
    • WebSocket:允许服务器主动向客户端发送消息,实现服务器推送。
  3. 连接持久性
    • REST:每次请求/响应完成后,连接通常会关闭,除非使用了HTTP持久连接(HTTP/1.1的keep-alive或HTTP/2)。
    • WebSocket:建立了一个持久的连接,可以保持开放状态,用于实时双向通信。
  4. 使用场景
    • REST:适用于需要获取、创建、修改或删除网络资源的场景,如API调用、Web服务等。
    • WebSocket:适用于需要实时数据传输的场景,如在线游戏、实时聊天应用、股票行情更新等。
  5. 数据格式
    • REST:通常使用JSON或XML作为数据交换格式。
    • WebSocket:可以传输任何格式的数据,包括文本和二进制数据。
  6. 性能
    • REST:可能涉及较多的HTTP请求和响应,对于需要频繁通信的场景可能性能较低。
    • WebSocket:由于连接持久,减少了建立和关闭连接的开销,适用于需要频繁通信的场景。
  7. 安全性
    • REST:可以通过HTTPS提供安全通信。
    • WebSocket:也可以通过WSS(WebSocket Secure)提供安全通信。
  8. 兼容性
    • REST:几乎所有的Web服务器和客户端都支持HTTP协议。
    • WebSocket:需要服务器和客户端支持WebSocket协议。
  9. API设计
    • REST:强调资源的统一接口和无状态操作,易于理解和使用。
    • WebSocket:提供了一种更为灵活的通信方式,但可能需要更复杂的逻辑来管理连接和数据流。

总的来说,REST和WebSocket各有优势,选择哪种技术取决于具体的应用需求和场景。

# HTTP缓存怎么实现的

HTTP 缓存 是一种通过在客户端(如浏览器)或中间服务器(如代理服务器、CDN)存储资源副本,减少服务器负载并提高网页加载速度的技术。它通过缓存经常请求的资源,避免每次都向服务器发送相同的请求,从而提升性能。

HTTP 缓存的基本概念

  1. 强缓存(强制缓存 / 本地缓存)
    • 浏览器直接从缓存中读取资源,而不与服务器通信。
    • 如果缓存资源在缓存期间有效,浏览器不会向服务器发送请求。
  2. 协商缓存(对比缓存)
    • 浏览器会向服务器验证缓存是否仍然有效。
    • 如果资源没有更改,服务器会返回 304 Not Modified,浏览器继续使用缓存中的副本。

缓存相关的 HTTP 响应头

服务器通过响应头告诉客户端如何缓存资源。以下是常用的缓存控制头:

  1. Cache-ControlCache-Control 是控制缓存行为的最重要的 HTTP 头,可以定义资源的缓存策略。常见的 Cache-Control 指令包括:

    • max-age:定义资源可以缓存的最大时间(以秒为单位)。例如,max-age=3600 表示缓存 1 小时。

    • no-cache:每次请求都会去服务器进行验证,协商缓存是否有效。

    • no-store:禁止任何缓存,无论是强缓存还是协商缓存。

    • public:资源可以被任何缓存(包括客户端和代理服务器)缓存。

    • private:资源只能被客户端缓存,不能被代理服务器缓存。

    • must-revalidate:在缓存过期后,必须向服务器验证资源是否还有效。

  2. Expires

    Expires 头部用于指定资源的过期时间,表示在此时间之前可以直接使用缓存。它是 HTTP/1.0 版本中的缓存机制,通常会被 Cache-Controlmax-age 覆盖。

  3. ETag

    ETag 是资源的唯一标识符,用于协商缓存。当客户端请求资源时,会带上 ETag,服务器通过对比 ETag 判断资源是否发生变化。

  4. Last-Modified

    Last-Modified 记录资源最后一次修改的时间。客户端可以通过 If-Modified-Since 请求头询问服务器该资源是否自该时间以来发生了变化。

强缓存与协商缓存的工作流程

  1. 强缓存:强缓存是浏览器在缓存资源有效期内直接从本地缓存中获取资源,不与服务器通信。常用的头部有 Cache-ControlExpires

    工作流程:

    • 浏览器发起请求并获取资源及其缓存策略(例如 Cache-Control: max-age=3600)。

    • 在 3600 秒内,浏览器再次请求该资源时,直接从本地缓存中读取资源,而不会发送请求到服务器。

  2. 协商缓存:当强缓存失效时,浏览器会与服务器进行通信,询问资源是否有更新。协商缓存通过 ETagLast-Modified 进行判断。

    工作流程:

    • 浏览器发送请求,附带 If-None-MatchIf-Modified-Since 头部。

    • 服务器检查资源是否发生变化:

      • 如果资源未变化,服务器返回 304 Not Modified,浏览器使用本地缓存的副本。
      • 如果资源已变化,服务器返回最新的资源及状态码 200

缓存的优先级

  1. Cache-Control vs Expires: 如果 Cache-ControlExpires 同时存在,Cache-Controlmax-age 优先级更高。
  2. ETag vs Last-ModifiedETag 的优先级高于 Last-Modified。如果两者都存在,服务器通常会首先比较 ETag,然后再检查 Last-Modified

# 什么是幂等性?如何设计一个幂等的接口?

幂等性(Idempotence)是指一个操作多次执行和一次执行的效果相同,不会因为多次请求而产生额外的副作用。

在数学中,如果函数 f(x) 满足 f(f(x)) = f(x),则称该函数是幂等的。在计算机科学和网络通信中,幂等性通常指以下两种情况:

  1. 重复请求:对于同一个操作的多次请求,系统应该能够处理重复的请求而不产生额外的副作用。
  2. 并发请求:对于同时发起的多个相同请求,系统应该能够确保操作只被执行一次。

设计幂等接口时,需要考虑以下几个关键点:

  1. 根据 HTTP 方法的语义设计

    • GET:天然幂等,因为它只是查询资源,不会修改服务器状态。

    • DELETE:确保重复删除同一个资源不会出错,比如返回 "Resource Not Found" 表示已经删除。

    • PUT:确保更新逻辑只会修改指定资源,比如通过资源 ID 定位并更新。

  2. 唯一标识符:为每个请求分配一个唯一的标识符(如订单号、交易ID等),确保可以通过这个标识符检查操作是否已经执行过。

  3. 状态检查:在执行操作前,检查当前状态是否允许执行该操作。如果操作已经完成或正在进行中,则拒绝重复的请求。

  4. 数据库设计:在数据库中设计适当的约束(如唯一索引)和事务控制,确保数据的一致性和完整性。

# 传输层

TCP 协议中的定时器

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

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

① 若在计时器截止之前发送方收到了接收方的 ACK 报文,则撤销该计时器;

② 若计时器截止时间内并没有收到接收方的 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 是如何保证可靠性的

数据分块: 应用数据被分割成 TCP 认为最适合发送的数据块。

序列号和确认应答:TCP 给发送的每一个包进行编号,在传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答,即发送 ACK 报文,这个 ACK 报文当中带有对应的确认序列号,告诉发送方成功接收了哪些数据以及下一次的数据从哪里开始发。除此之外,接收方可以根据序列号对数据包进行排序,把有序数据传送给应用层,并丢弃重复的数据。

校验和: TCP 将保持它首部和数据部分的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到报文段的检验和有差错,TCP 将丢弃这个报文段并且不确认收到此报文段。

流量控制: TCP 连接的双方都有一个固定大小的缓冲空间,发送方发送的数据量不能超过接收端缓冲区的大小。当接收方来不及处理发送方的数据,会提示发送方降低发送的速率,防止产生丢包。TCP 通过滑动窗口协议来支持流量控制机制。

拥塞控制: 当网络某个节点发生拥塞时,减少数据的发送。

ARQ协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。

超时重传: 当 TCP 发出一个报文段后,它启动一个定时器,等待目的端确认收到这个报文段。如果超过某个时间还没有收到确认,将重发这个报文段。

# 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 超时重传的原理

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

# TCP 的停止等待协议是什么

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

img

① 无差错传输

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

② 出现差错

如上述右图所示,发送方发送的报文出现差错导致接收方不能正确接收数据,出现差错的情况主要分为两种:

  • 发送方发送的 Msg 1 在中途丢失了,接收方完全没收到数据。
  • 接收方收到 Msg 1 后检测出现了差错,直接丢弃 Msg 1。

上面两种情形,接收方都不会回任何消息给发送方,此时就会触发超时传输机制,即发送方在等待一段时间后仍然没有收到接收方的确认,就认为刚才发送的数据丢失了,因此重传前面发送过的数据。

img

③ 确认丢失

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

④ 确认迟到

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

上述四种情形即停止等待协议中所出现的所有可能情况。

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

# TCP 流量控制与拥塞控制

  • 流量控制

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

  • 拥塞控制

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

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

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

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

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

# TCP 粘包问题

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

① 发送方写入的数据大于套接字缓冲区的大小,此时将发生拆包。

② 发送方写入的数据小于套接字缓冲区大小,由于 TCP 默认使用 Nagle 算法,只有当收到一个确认后,才将分组发送给对端,当发送方收集了多个较小的分组,就会一起发送给对端,这将会发生粘包。

③ 进行 MSS (最大报文长度)大小的 TCP 分段,当 TCP 报文的数据部分大于 MSS 的时候将发生拆包。

④ 发送方发送的数据太快,接收方处理数据的速度赶不上发送端的速度,将发生粘包。

常见解决方法

① 在消息的头部添加消息长度字段,服务端获取消息头的时候解析消息长度,然后向后读取相应长度的内容。

② 固定消息数据的长度,服务端每次读取既定长度的内容作为一条完整消息,当消息不够长时,空位补上固定字符。但是该方法会浪费网络资源。

③ 设置消息边界,也可以理解为分隔符,服务端从数据流中按消息边界分离出消息内容,一般使用换行符。

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

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

# TCP 报文包含哪些信息

TCP 报文是 TCP 传输的的数据单元,也叫做报文段,其报文格式如下图所示:

img

  • 源端口和目的端口号:它用于多路复用/分解来自或送往上层应用的数据,其和 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 三次握手和四次挥手过程中,通信双方交换的报文只包含头部信息,数据部分为空,只有当连接成功建立后,TCP 包才真正携带数据。

# SYN FLOOD 是什么

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

# 为什么服务端易受到 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 状态【详解见问题 7, 8, 9】

  • 客户端主动关闭连接

当客户端主动关闭连接时,我们并不需要关心 TIME-WAIT 状态过多造成的问题,但是需要关注服务端保持大量的 CLOSE-WAIT 状态时会产生的问题【见问题 10 的解决方法】

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

# 网络层

# IP 协议的定义和作用

IP 协议(Internet Protocol)又称互联网协议,是支持网间互联的数据包协议。该协议工作在网络层,主要目的就是为了提高网络的可扩展性,和传输层 TCP 相比,IP 协议提供一种无连接/不可靠、尽力而为的数据包传输服务,其与TCP协议(传输控制协议)一起构成了TCP/IP 协议族的核心。IP 协议主要有以下几个作用:

  • 寻址和路由:在IP 数据包中会携带源 IP 地址和目的 IP 地址来标识该数据包的源主机和目的主机。IP 数据报在传输过程中,每个中间节点(IP 网关、路由器)只根据网络地址进行转发,如果中间节点是路由器,则路由器会根据路由表选择合适的路径。IP 协议根据路由选择协议提供的路由信息对 IP 数据报进行转发,直至抵达目的主机。
  • 分段与重组:IP 数据包在传输过程中可能会经过不同的网络,在不同的网络中数据包的最大长度限制是不同的,IP 协议通过给每个 IP 数据包分配一个标识符以及分段与组装的相关信息,使得数据包在不同的网络中能够传输,被分段后的 IP 数据报可以独立地在网络中进行转发,在到达目的主机后由目的主机完成重组工作,恢复出原来的 IP 数据包。

# 域名和 IP 的关系,一个 IP 可以对应多个域名吗

IP 在同一个网络中是唯一的,用来标识每一个网络上的设备,其相当于一个人的身份证号;域名在同一个网络中也是唯一的,就像一个人的名字,绰号。假如你有多个不同的绰号,你的朋友可以用其中任何一个绰号叫你,但你的身份证号码却是唯一的。由此我们可以看出一个域名只能对应一个 IP 地址,是一对一的关系;而一个 IP 却可以对应多个域名,是一对多的关系。

一个域名可以对应多个IP地址,这种能力主要得益于DNS(域名系统)的工作原理

在DNS记录中,A记录(Address Record)用于将域名映射到一个IPv4地址

一个域名可以有多个A记录或AAAA记录,这意味着它可以对应多个IPv4或IPv6地址

# IPV4 地址不够如何解决

  • DHCP:动态主机配置协议。动态分配 IP 地址,只给接入网络的设备分配IP地址,因此同一个 MAC 地址的设备,每次接入互联网时,得到的IP地址不一定是相同的,该协议使得空闲的 IP 地址可以得到充分利用。
  • CIDR:无类别域间路由。CIDR 消除了传统的 A 类、B 类、C 类地址以及划分子网的概念,因而更加有效的分配 IPv4 的地址空间,但无法从根本上解决地址耗尽问题。
  • NAT:网络地址转换协议。我们知道属于不同局域网的主机可以使用相同的 IP 地址,从而一定程度上缓解了 IP 资源枯竭的问题。然而主机在局域网中使用的 IP 地址是不能在公网中使用的,当局域网主机想要与公网进行通信时, NAT 方法可以将该主机 IP 地址转换成全球 IP 地址。该协议能够有效解决 IP 地址不足的问题。
  • IPv6 :作为接替 IPv4 的下一代互联网协议,其可以实现 2 的 128 次方个地址,而这个数量级,即使是给地球上每一颗沙子都分配一个IP地址,该协议能够从根本上解决 IPv4 地址不够用的问题。
# IPv4 和 IPv6 的区别?

地址长度

  • IPv4:地址长度为 32 位(二进制位),通常用点分十进制表示,如:192.168.1.1
    • 地址数量:大约 42 亿个(2322^{32}232)。
  • IPv6:地址长度为 128 位,通常用冒分十六进制表示,如:2001:0db8:85a3:0000:0000:8a2e:0370:7334
    • 地址数量:大约 21282^{128}2128,理论上几乎是无限的(约 3.4×10383.4 \times 10^{38}3.4×1038 个地址)。

地址表示

  • IPv4:点分十进制表示,分为 4 个八位字节(4 个字节),例如:192.168.1.1
  • IPv6:冒分十六进制表示,由 8 组 16 位(每组用冒号分隔),例如:2001:0db8:85a3:0000:0000:8a2e:0370:7334

# 路由器的分组转发流程

① 从 IP 数据包中提取出目的主机的 IP 地址,找到其所在的网络;

② 判断目的 IP 地址所在的网络是否与本路由器直接相连,如果是,则不需要经过其它路由器直接交付,否则执行 ③;

③ 检查路由表中是否有目的 IP 地址的特定主机路由。如果有,则按照路由表传送到下一跳路由器中,否则执行 ④;

④ 逐条检查路由表,若找到匹配路由,则按照路由表转发到下一跳路由器中,否则执行步骤 ⑤;

⑤ 若路由表中设置有默认路由,则按照默认路由转发到默认路由器中,否则执行步骤 ⑥;

⑥ 无法找到合适路由,向源主机报错。

# 路由器和交换机的区别

  • 交换机:交换机用于局域网,利用主机的物理地址(MAC 地址)确定数据转发的目的地址,它工作与数据链路层。
  • 路由器:路由器通过数据包中的目的 IP 地址识别不同的网络从而确定数据转发的目的地址,网络号是唯一的。路由器根据路由选择协议和路由表信息从而确定数据的转发路径,直到到达目的网络,它工作于网络层。

# ICMP 协议概念/作用

ICMP(Internet Control Message Protocol)是因特网控制报文协议,主要是实现 IP 协议中未实现的部分功能,是一种网络层协议。该协议并不传输数据,只传输控制信息来辅助网络层通信。其主要的功能是验证网络是否畅通(确认接收方是否成功接收到 IP 数据包)以及辅助 IP 协议实现可靠传输(若发生 IP 丢包,ICMP 会通知发送方 IP 数据包被丢弃的原因,之后发送方会进行相应的处理)。

# ICMP 的应用

  • Ping

Ping(Packet Internet Groper),即因特网包探测器,是一种工作在网络层的服务命令,主要用于测试网络连接量。本地主机通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送 Echo 响应报文,Ping 会根据时间和成功响应的次数估算出数据包往返时间以及丢包率从而推断网络是否通常、运行是否正常等。

  • TraceRoute

TraceRoute 是 ICMP 的另一个应用,其主要用来跟踪一个分组从源点耗费最少 TTL 到达目的地的路径。TraceRoute 通过逐渐增大 TTL 值并重复发送数据报来实现其功能,首先,TraceRoute 会发送一个 TTL 为 1 的 IP 数据报到目的地,当路径上的第一个路由器收到这个数据报时,它将 TTL 的值减 1,此时 TTL = 0,所以路由器会将这个数据报丢掉,并返回一个差错报告报文,之后源主机会接着发送一个 TTL 为 2 的数据报,并重复此过程,直到数据报能够刚好到达目的主机。此时 TTL = 0,因此目的主机要向源主机发送 ICMP 终点不可达差错报告报文,之后源主机便知道了到达目的主机所经过的路由器 IP 地址以及到达每个路由器的往返时间。

# 两台电脑连起来后 ping 不通,你觉得可能存在哪些问题?

  1. 首先看网络是否连接正常,检查网卡驱动是否正确安装。
  2. 局域网设置问题,检查 IP 地址是否设置正确。
  3. 看是否被防火墙阻拦(有些设置中防火墙会对 ICMP 报文进行过滤),如果是的话,尝试关闭防火墙 。
  4. 看是否被第三方软件拦截。
  5. 两台设备间的网络延迟是否过大(例如路由设置不合理),导致 ICMP 报文无法在规定的时间内收到。

# ARP 地址解析协议的原理和地址解析过程

ARP(Address Resolution Protocol)是地址解析协议的缩写,该协议提供根据 IP 地址获取物理地址的功能,它工作在第二层,是一个数据链路层协议,其在本层和物理层进行联系,同时向上层提供服务。当通过以太网发送 IP 数据包时,需要先封装 32 位的 IP 地址和 48位 MAC 地址。在局域网中两台主机进行通信时需要依靠各自的物理地址进行标识,但由于发送方只知道目标 IP 地址,不知道其 MAC 地址,因此需要使用地址解析协议。 ARP 协议的解析过程如下:

① 首先,每个主机都会在自己的 ARP 缓冲区中建立一个 ARP 列表,以表示 IP 地址和 MAC 地址之间的对应关系;

② 当源主机要发送数据时,首先检查 ARP 列表中是否有 IP 地址对应的目的主机 MAC 地址,如果存在,则可以直接发送数据,否则就向同一子网的所有主机发送 ARP 数据包。该数据包包括的内容有源主机的 IP 地址和 MAC 地址,以及目的主机的 IP 地址。

③ 当本网络中的所有主机收到该 ARP 数据包时,首先检查数据包中的 目的 主机IP 地址是否是自己的 IP 地址,如果不是,则忽略该数据包,如果是,则首先从数据包中取出源主机的 IP 和 MAC 地址写入到 ARP 列表中,如果已经存在,则覆盖,然后将自己的 MAC 地址写入 ARP 响应包中,告诉源主机自己是它想要找的 MAC 地址。

④ 源主机收到 ARP 响应包后。将目的主机的 IP 和 MAC 地址写入 ARP 列表,并利用此信息发送数据。如果源主机一直没有收到 ARP 响应数据包,表示 ARP 查询失败。

# 网络地址转换 NAT

NAT(Network Address Translation),即网络地址转换,它是一种把内部私有网络地址翻译成公有网络 IP 地址的技术。该技术不仅能解决 IP 地址不足的问题,而且还能隐藏和保护网络内部主机,从而避免来自外部网络的攻击。

NAT 的实现方式主要有三种:

  • 静态转换:内部私有 IP 地址和公有 IP 地址是一对一的关系,并且不会发生改变。通过静态转换,可以实现外部网络对内部网络特定设备的访问,这种方式原理简单,但当某一共有 IP 地址被占用时,跟这个 IP 绑定的内部主机将无法访问 Internet。
  • 动态转换:采用动态转换的方式时,私有 IP 地址每次转化成的公有 IP 地址是不唯一的。当私有 IP 地址被授权访问 Internet 时会被随机转换成一个合法的公有 IP 地址。当 ISP 通过的合法 IP 地址数量略少于网络内部计算机数量时,可以采用这种方式。
  • 端口多路复用:该方式将外出数据包的源端口进行端口转换,通过端口多路复用的方式,实现内部网络所有主机共享一个合法的外部 IP 地址进行 Internet 访问,从而最大限度地节约 IP 地址资源。同时,该方案可以隐藏内部网络中的主机,从而有效避免来自 Internet 的攻击。

# TTL 是什么?有什么作用

TTL 是指生存时间,简单来说,它表示了数据包在网络中的时间。每经过一个路由器后 TTL 就减一,这样 TTL 最终会减为 0 ,当 TTL 为 0 时,则将数据包丢弃。通过设置 TTL 可以避免这两个路由器之间形成环导致数据包在环路上死转的情况,由于有了 TTL ,当 TTL 为 0 时,数据包就会被抛弃。

# 运输层协议和网络层协议的区别

网络层协议负责提供主机间的逻辑通信;运输层协议负责提供进程间的逻辑通信。

# 数据链路层

# MAC 地址和 IP 地址分别有什么作用

  • MAC 地址是数据链路层和物理层使用的地址,是写在网卡上的物理地址。MAC 地址用来定义网络设备的位置。
  • IP 地址是网络层和以上各层使用的地址,是一种逻辑地址。IP 地址用来区别网络上的计算机。

# 为什么有了 MAC 地址还需要 IP 地址

如果我们只使用 MAC 地址进行寻址的话,我们需要路由器记住每个 MAC 地址属于哪一个子网,不然每一次路由器收到数据包时都要满世界寻找目的 MAC 地址。而我们知道 MAC 地址的长度为 48 位,也就是说最多总共有 2 的 48 次方个 MAC 地址,这就意味着每个路由器需要 256 T 的内存,这显然是不现实的。

和 MAC 地址不同,IP 地址是和地域相关的,在一个子网中的设备,我们给其分配的 IP 地址前缀都是一样的,这样路由器就能根据 IP 地址的前缀知道这个设备属于哪个子网,剩下的寻址就交给子网内部实现,从而大大减少了路由器所需要的内存。

# 为什么有了 IP 地址还需要 MAC 地址

只有当设备连入网络时,才能根据他进入了哪个子网来为其分配 IP 地址,在设备还没有 IP 地址的时候或者在分配 IP 地址的过程中,我们需要 MAC 地址来区分不同的设备。

# 私网地址和公网地址之间进行转换:同一个局域网内的两个私网地址,经过转换之后外面看到的一样吗

当采用静态或者动态转换时,由于一个私网 IP 地址对应一个公网地址,因此经过转换之后的公网 IP 地址是不同的;而采用端口复用方式的话,在一个子网中的所有地址都采用一个公网地址,但是使用的端口是不同的。

# 以太网中的 CSMA/CD 协议

CSMA/CD 为载波侦听多路访问/冲突检测,是像以太网这种广播网络采用的一种机制,我们知道在以太网中多台主机在同一个信道中进行数据传输,CSMA/CD 很好的解决了共享信道通信中出现的问题,它的工作原理主要包括两个部分:

  • 载波监听:当使用 CSMA/CD 协议时,总线上的各个节点都在监听信道上是否有信号在传输,如果有的话,表明信道处于忙碌状态,继续保持监听,直到信道空闲为止。如果发现信道是空闲的,就立即发送数据。
  • 冲突检测:当两个或两个以上节点同时监听到信道空闲,便开始发送数据,此时就会发生碰撞(数据的传输延迟也可能引发碰撞)。当两个帧发生冲突时,数据帧就会破坏而失去了继续传输的意义。在数据的发送过程中,以太网是一直在监听信道的,当检测到当前信道冲突,就立即停止这次传输,避免造成网络资源浪费,同时向信道发送一个「冲突」信号,确保其它节点也发现该冲突。之后采用一种二进制退避策略让待发送数据的节点随机退避一段时间之后重新。

# 数据链路层上的三个基本问题

封装成帧:将网络层传下来的分组前后分别添加首部和尾部,这样就构成了帧。首部和尾部的一个重要作用是帧定界,也携带了一些必要的控制信息,对于每种数据链路层协议都规定了帧的数据部分的最大长度。

透明传输:帧使用首部和尾部进行定界,如果帧的数据部分含有和首部和尾部相同的内容, 那么帧的开始和结束的位置就会判断错,因此需要在数据部分中出现有歧义的内容前边插入转义字符,如果数据部分出现转义字符,则在该转义字符前再加一个转义字符。在接收端进行处理之后可以还原出原始数据。这个过程透明传输的内容是转义字符,用户察觉不到转义字符的存在。

差错检测:目前数据链路层广泛使用循环冗余检验(CRC)来检查数据传输过程中是否产生比特差错。

# PPP 协议

互联网用户通常需要连接到某个 ISP 之后才能接入到互联网,PPP(点对点)协议是用户计算机和 ISP 进行通信时所使用的数据链路层协议。点对点协议为点对点连接上传输多协议数据包提供了一个标准方法。该协议设计的目的主要是用来通过拨号或专线方式建立点对点连接发送数据,使其成为各种主机、网桥和路由器之间简单连接的一种解决方案。

PPP 协议具有以下特点:

  • PPP 协议具有动态分配 IP 地址的能力,其允许在连接时刻协商 IP 地址。
  • PPP 支持多种网络协议,例如 TCP/IP、NETBEUI 等。
  • PPP 具有差错检测能力,但不具备纠错能力,所以 PPP 是不可靠传输协议。
  • 无重传的机制,网络开销小,速度快。
  • PPP 具有身份验证的功能。

# 为什么 PPP 协议不使用序号和确认机制

  • IETF 在设计因特网体系结构时把齐总最复杂的部分放在 TCP 协议中,而网际协议 IP 则相对比较简单,它提供的是不可靠的数据包服务,在这种情况下,数据链路层没有必要提供比 IP 协议更多的功能。若使用能够实现可靠传输的数据链路层协议,则开销就要增大,这在数据链路层出现差错概率不大时是得不偿失的。
  • 即使数据链路层实现了可靠传输,但其也不能保证网络层的传输也是可靠的,当数据帧在路由器中从数据链路层上升到网络层后,仍有可能因为网络层拥塞而被丢弃。
  • PPP 协议在帧格式中有帧检验序列,对每一个收到的帧,PPP 都会进行差错检测,若发现差错,则丢弃该帧。

# 物理层

# 物理层主要做什么事情

作为 OSI 参考模型最低的一层,物理层是整个开放系统的基础,该层利用传输介质为通信的两端建立、管理和释放物理连接,实现比特流的透明传输。物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流,其尽可能地屏蔽掉不同种类传输媒体和通信手段的差异,使物理层上面的数据链路层感觉不到这些差异,这样就可以使数据链路层只考虑完成本层的协议和服务,而不必考虑网络的具体传输媒体和通信手段是什么。

# 主机之间的通信方式

单工通信:也叫单向通信,发送方和接收方是固定的,消息只能单向传输。例如采集气象数据、家庭电费,网费等数据收集系统,或者打印机等应用主要采用单工通信。 半双工通信:也叫双向交替通信,通信双方都可以发送消息,但同一时刻同一信道只允许单方向发送数据。例如传统的对讲机使用的就是半双工通信。 全双工通信:也叫双向同时通信,全双工通信允许通信双方同时在两个方向是传输,其要求通信双方都具有独立的发送和接收数据的能力。例如平时我们打电话,自己说话的同时也能听到对面的声音。

# 通道复用技术

频分复用(FDM,Frequency Division Multiplexing) 频分复用将传输信道的总带宽按频率划分为若干个子频带或子信道,每个子信道传输一路信号。用户分到一定的频带后,在数据传输的过程中自始至终地占用这个频带。由于每个用户所分到的频带不同,使得传输信道在同一时刻能够支持不同用户进行数据传输,从而实现复用。除了传统意义上的 FDM 外,目前正交频分复用(OFDM)已在高速通信系统中得到广泛应用。

时分复用(TDM,Time Division Multiplexing) 顾名思义,时分复用将信道传输信息的时间划分为若干个时间片,每一个时分复用的用户在每一个 TDM 帧中占用固定时隙进行数据传输。用户所分配到的时隙是固定的,所以时分复用有时也叫做同步时分复用。这种分配方式能够便于调节控制,但是也存在缺点,当某个信道空闲时,其他繁忙的信道无法占用该空闲信道,因此会降低信道利用率。

波分复用(WDM,Wavelength Division Multiplexing) 在光通信领域通常按照波长而不是频率来命名,因为光的频率和波长具有单一对应关系,因此 WDM 本质上也是 FDM,光通信系统中,通常由光来运载信号进行传输,WDM 是在一条光纤上传输多个波长光信号,其将 1 根光纤看做多条「虚拟」光纤,每条「虚拟」光纤工作在不同的波长上,从而极大地提高了光纤的传输容量。

码分复用(CDM,Code Division Multiplexing) 码分复用是靠不同的编码来区分各路原始信号的一种复用方式,不同的用户使用相互正交的码字携带信息。由于码组相互正交,因此接收方能够有效区分不同的用户数据,从而实现每一个用户可以在同样的时间在同样的频带进行数据传输,频谱资源利用率高。其主要和各种多址接入技术相结合从而产生各种接入技术,包括无线和优先接入。

# 几种常用的宽带接入技术

我们一般将速率超过 1 Mbps 的接入称为宽带接入,目前常用的宽带接入技术主要包括:ADSL 和 FTTx + LAN。

  • ADSL

ADSL 全称为非对称用户数字环路,是铜线宽带接入技术的一种。其非对称体现在用户上行和下行的传输速率不相等,一般上行速率较低,下行速率高。这种接入技术适用于有宽带业务需求的家庭用户或者中小型商务用户等。

  • FTTx + LAN

其中 FTTx 英文翻译为 Fiber To The X,这里的 X 指任何地方,我们可以理解为光纤可以接入到任何地方,而 LAN 指的是局域网。FTTx + LAN 是一种在接入网全部或部分采用光纤传输介质,构成光纤用户线路,从而实现用户高速上网的接入技术,其中用户速率可达 20 Mbps。这种接入技术投资规模小,网络拓展性强,网络可靠稳定,使得其应用广泛,目前是城市汇总较为普及的一种宽带接入技术。

其它还有 光纤同轴混合网(HFC)、光接入技术(有源和无源光纤系统)和无线接入技术等等。

Last Updated: 2/25/2025, 2:22:49 PM

消息提示

🐳 欢迎关注〖JavaKeeper〗🐳
🎉 500 + Java开发电子书免费获取 🎉