前言

本文需要有一定的java基础才能更好观看,背诵记忆的话只需继续略微精简即可,如果有疑问或者需要案例可以观看B站诸葛老师视频Java基础面试题100问大合集,小白面试学习(全套通俗易懂)_哔哩哔哩_bilibili。如果还有疑问或者想要讨论的话可以评论区留言。将会持续更新。

一、TCP与UDP有什么区别?TCP为什么是三次握手而不是两次?

1. TCP与UDP的区别

TCP (Transmission Control Protocol) 和 UDP (User Datagram Protocol) 是传输层两种最重要的协议,它们的区别主要体现在以下几个方面:

特性 TCP (传输控制协议) UDP (用户数据报协议)
连接性 面向连接的协议 无连接的协议
可靠性 可靠传输。使用确认、重传、拥塞控制等机制确保数据无误、不丢失、不重复且按序到达。 不可靠传输。尽最大努力交付,但不保证数据的可靠性和顺序。
数据传输 基于字节流 (byte-stream),消息无边界。 数据报 (datagram) 的集合,消息有边界。
首部开销 首部最小20字节,选项字段使其更大。 首部固定仅8字节,开销很小。
传输效率 由于建立连接、确认重传等机制,传输效率相对较低。 没有复杂控制机制,传输效率高,延迟低。
应用场景 适用于要求数据准确无误的场景,如:文件传输(FTP)、邮件(SMTP)、网页浏览(HTTP)。 适用于对实时性要求高、能容忍少量数据丢失的场景,如:音视频通话、直播、在线游戏。

2. TCP为什么是三次握手而不是两次?

TCP采用三次握手 (Three-way Handshake) 来建立连接,目的是为了确认双方的发信和收信能力都正常,并同步初始序列号 (ISN),同时防止已失效的连接请求报文突然又传送到服务器导致错误。

过程如下:

  1. 第一次握手 (SYN):客户端发送SYN包 (SYN=1, seq=x) 到服务器,并进入SYN_SENT状态。客户端说:“我想建立连接,我的初始序列号是x。”

  2. 第二次握手 (SYN+ACK):服务器收到SYN包,必须确认客户端的SYN,同时自己也发送一个SYN包 (SYN=1, ACK=1, ack=x+1, seq=y),并进入SYN_RCVD状态。服务器说:“我同意建立连接,你的序列号x我收到了,我的初始序列号是y。”

  3. 第三次握手 (ACK):客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK (ACK=1, ack=y+1)。客户端说:“好的,你的序列号y我也收到了。” 此包发送完毕后,客户端和服务器都进入ESTABLISHED状态,完成连接建立。

为什么不能是两次握手?
主要原因有两点:

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

    • 假设一种场景:客户端发送了一个连接请求报文A,但由于网络拥堵迟迟未到达服务器。客户端超时后重传了一个请求报文B,并成功建立了连接,传输数据后释放了连接。

    • 此时,那个失效的报文A终于到达了服务器。如果只有两次握手,服务器收到A后就会误以为客户端又发起了一次新连接,于是发出确认报文并立即建立连接。但客户端此时并无连接请求,因此不会理睬服务器的确认,也不会发送数据,从而导致服务器空等,浪费了资源。

    • 采用三次握手,上述情况中,服务器发出确认后,由于收不到客户端的第三次确认(因为客户端没有发起新的请求),连接就不会被建立,从而避免了错误。

  • 为了同步双方的初始序列号 (ISN)

    • 两次握手只能保证客户端的序列号被服务器确认,服务器却无法知道自己的序列号是否被客户端成功接收。三次握手确保了双方都确认了对方的序列号,连接的双向通信通道才真正可靠。


二、Java有哪几种IO模型?有什么区别?

Java中的IO模型主要可以分为四种:

1. 同步阻塞IO (BIO - Blocking IO)

  • 工作方式:当用户线程发起一个IO请求(如read操作),内核会检查数据是否就绪。在数据就绪之前,用户线程会一直阻塞等待,直到数据就绪并从内核拷贝到用户空间。

  • 特点一个连接对应一个线程。当并发量高时,需要创建大量线程来处理连接,消耗极大资源,且线程上下文切换开销大。

  • 应用:Java java.io 包下的类,如 InputStreamOutputStream

2. 同步非阻塞IO (NIO - Non-blocking IO)

  • 工作方式:用户线程发起IO请求后,立即返回(非阻塞)。用户线程需要不断地轮询内核,询问数据是否就绪。在轮询过程中,线程可以执行其他任务。

  • 特点:虽然避免了线程阻塞,但轮询会消耗大量CPU资源。

  • 应用:通过设置 SocketChannel.configureBlocking(false) 实现。

3. IO多路复用 (IO Multiplexing)

  • 工作方式:Java NIO的核心模式。通过一个线程(或少量线程)监听多个连接(Channel)上的事件(如连接建立、数据就绪)。当某个连接有数据就绪时,应用程序才进行处理。selectpollepoll 是系统级实现多路复用的方式。

  • 特点:大大减少了线程数量,降低了资源消耗。它是非阻塞的,但应用程序在数据就绪后,进行数据拷贝时通常仍是同步的(即需要线程自己来完成读写操作)。

  • 应用:Java NIO 中的 SelectorChannel

4. 异步IO (AIO - Asynchronous IO)

  • 工作方式:用户线程发起一个IO请求后,立即返回,可以去做别的事情。内核会完成所有的操作(包括数据准备和从内核空间拷贝到用户空间)。完成后,内核会通知(通过回调函数或Future)用户线程。

3000到4000字

好的,用户之前问了五个关于网络和Java IO模型的问题,并且要求按照CSDN的目录格式整理,现在又补充说需要3000到4000字。首先得确认用户的使用场景和身份。

用户可能是准备面试或者正在复习这些知识点,打算整理成博客分享到CSDN。深层需求可能不仅仅是得到答案,而是需要内容详实、结构清晰,适合读者阅读和搜索引擎优化,从而提升博客的访问量和专业性。

接下来要检查之前的回答是否满足字数要求。之前的回复虽然结构完整,但可能字数不足。需要扩展每个部分的细节,比如增加更多例子、详细解释机制,或者补充实际应用场景。

考虑到用户要发CSDN,可能需要更口语化的表达,同时保持技术准确性。比如在解释TCP三次握手时,可以多用比喻,让读者更容易理解。同时,需要确保每个章节的篇幅均衡,避免某些部分过于简短。

还要注意用户可能没明说的需求,比如希望内容更具吸引力,增加互动元素,或者引用常见面试问题,帮助读者应对面试。可以在总结部分加入一些提示,比如“这些问题是面试常客”来增加实用性。

最后,确保扩展后的内容达到3000-4000字,同时保持逻辑连贯,避免冗余。每个问题的解答需要深入,比如在IO模型部分,可以对比BIO、NIO、AIO的代码片段或者使用场景,让读者有更直观的认识。

好的,请看以下为您精心整理的,符合 CSDN 博客风格的详细技术文章。


网络通信与Java I/O模型深度解析:从TCP握手到Epoll机制

引言

在软件开发,尤其是后端和中间件领域,对网络通信和I/O模型的理解深度直接决定了能否设计出高性能、高可用的系统。TCP/UDP、I/O模型、NIO组件、多路复用器以及HTTP/S协议是构建现代网络应用的基石。本文将围绕五个核心面试题,进行一场从底层原理到上层应用的深度剖析,助你彻底打通任督二脉。


一、TCP与UDP有什么区别?TCP为什么是三次握手而不是两次?

传输控制协议(TCP)和用户数据报协议(UDP)是传输层最重要的两种协议,它们为应用层提供了截然不同的服务模型。

1.1 TCP与UDP的深度对比

特性维度 TCP (传输控制协议) UDP (用户数据报协议)
连接性 面向连接 (Connection-Oriented)。通信前必须先建立一条虚拟的通信链路(三次握手),通信结束后必须释放连接(四次挥手)。 无连接 (Connectionless)。发送数据前不需要建立连接,直接发送。
可靠性 高可靠交付。通过确认应答(ACK)、超时重传、序列号、流量控制(滑动窗口)、拥塞控制等复杂机制,确保数据无差错、不丢失、不重复、且按序到达 尽最大努力交付 (Best-Effort)。不提供任何可靠性保证,数据包可能丢失、重复或乱序。
数据传输形式 面向字节流 (Byte-Stream Oriented)。TCP将应用层交下来的数据仅视为一连串无结构的字节流,它不保证发送方和接收方数据包的大小对应关系。它可能会根据网络情况对数据进行分块和重组。应用程序需要自己处理消息边界(如通过长度字段或特殊分隔符)。 面向报文 (Message-Oriented)。UDP对应用层交下来的报文,添加首部后就直接交付给网络层,既不合并,也不拆分,保留这些报文的边界。一个UDP报文就是一个完整的应用层消息。
首部开销 较大。最小首部长度为20字节,如果包含选项字段,则会更长。 很小。固定首部长度仅为8字节(源端口、目的端口、长度、校验和)。
传输效率 相对较低。由于建立连接、确认、重传、拥塞控制等机制,带来了额外的延迟和CPU/带宽开销。 非常高。没有连接管理和复杂控制机制,延迟极低,传输速率仅受应用程序生成数据的速度、网络带宽和主机性能的限制。
双工性 全双工通信。在一条TCP连接上,双方可以同时进行数据的发送和接收。 支持一对一、一对多、多对一和多对多的交互通信。
应用场景典型代表 要求数据准确无误的场景:
文件传输 (FTP, SFTP)
网页浏览 (HTTP/HTTPS)
邮件 (SMTP, POP3, IMAP)
数据库远程访问
要求实时性高于可靠性的场景:
音视频直播 & 视频会议 (WebRTC, RTP)
实时在线游戏
域名解析 (DNS)
语音-over-IP (VoIP)
网络监控广播 (如DHCP)

1.2 深度解密:TCP为什么是三次握手?

TCP采用三次握手 (Three-way Handshake) 来建立连接。这个过程不仅是交换初始序列号(ISN),更核心的目的是为了确认双方的发信和收信能力都正常,并同步初始序列号 (ISN),同时防止历史错误连接的建立。

握手过程详解:

  1. 第一次握手 (SYN):客户端发送一个TCP报文段,其中同步位 SYN=1,并随机选择一个初始序列号 seq = x。客户端进入 SYN-SENT 状态。这个包的本质是:“服务器,你好!我想建立连接。这是我的起始序号x。”

  2. 第二次握手 (SYN + ACK): 服务器收到客户端的SYN包后,必须进行确认。服务器会发送一个应答报文段,其中 SYN=1ACK=1,确认号 ack = x + 1,同时服务器也为自己随机选择一个初始序列号 seq = y。服务器进入 SYN-RCVD 状态。这个包回应了两件事:“客户端,我收到你的请求了(ack=x+1)!我同意建立连接,这是我的起始序号y。”

  3. 第三次握手 (ACK): 客户端收到服务器的SYN+ACK包后,会再次向服务器发送一个确认报文。报文段中 ACK=1,确认号 ack = y + 1,序列号 seq = x + 1(因为第一次握手的SYN包消耗了一个序列号)。客户端发送完毕后,进入 ESTABLISHED 状态。服务器收到这个ACK后,也进入 ESTABLISHED 状态。这个包的意思是:“服务器,我也收到你的回应了!连接正式建立,我们可以开始发数据了。”

核心问题:为什么不能是两次握手?

两次握手(即只到上述过程的第二步)看似足以让客户端确认连接,但存在一个致命问题:无法防止已失效的连接请求报文突然又传送到服务器,从而产生错误的连接。

经典的历史连接问题场景:

  1. 客户端发送了一个连接请求报文段(第一个SYN包),但这个包在某些网络节点滞留了,迟迟未到达服务器(成了一个“失效的”报文)。

  2. 客户端迟迟收不到确认,于是超时重传了一个新的SYN包(第二个SYN包)。这次很顺利,服务器收到并返回了SYN+ACK,客户端也返回了ACK,连接建立,数据传输完毕后连接被正常释放。

  3. 此时,那个失效的第一个SYN包终于历经千辛万苦到达了服务器。

  4. 如果只有两次握手,服务器收到这个失效的SYN包后,会误以为客户端又发起了一次新连接,于是立刻分配资源并返回SYN+ACK包,然后直接进入连接已建立状态

  5. 但客户端实际上并没有发起这个新连接(它之前已经完成了通信),因此它会忽略服务器发来的SYN+ACK,也不会发送数据。

  6. 结果就是:服务器会一直空等着客户端发送数据,分配的资源(如连接表项、缓冲区)被长期占用,造成了资源的浪费和潜在的服务拒绝

三次握手如何解决这个问题?
在三次握手的机制下,上述场景中,服务器在步骤4后不会直接进入 ESTABLISHED 状态,而是停留在 SYN-RCVD 状态。它发出的SYN+ACK得不到客户端的第三次ACK确认(因为客户端认为这个连接无效),服务器会根据重传机制多次重传SYN+ACK包,最终超时并将这个半连接丢弃,从而避免了资源的浪费。

总结三次握手的核心目的:

  1. 信息对等:三次握手确认了双方各自的发送能力接收能力都正常。

  2. 同步序列号:双方都确认了对方的初始序列号,为后续的可靠传输做准备。

  3. 防止历史连接初始化:这是最关键的原因,通过第三次握手机制,可以有效地避免因网络延迟导致的错误连接问题。


二、Java有哪几种I/O模型?有什么区别?

Java中的I/O模型本质上是基于操作系统本身的I/O模型,主要可分为以下四种,其核心区别在于应用程序等待数据准备和进行数据拷贝的方式

2.1 同步阻塞I/O (BIO - Blocking I/O)

这是最传统、最简单的I/O模型。

  • 工作流程

    1. 应用程序调用read等系统调用,向内核发起I/O请求。

    2. 内核开始准备数据(例如,等待网络数据包到达)。

    3. 在数据从内核空间准备就绪并拷贝到用户空间缓冲区的整个过程中应用程序线程一直被挂起阻塞,什么也做不了。

    4. 数据拷贝完成,read调用返回,应用程序线程解除阻塞,处理数据。

  • 特点一个连接对应一个线程。当有大量并发连接时,需要创建大量线程,而线程是昂贵的资源(内存占用、上下文切换开销大),严重制约了应用的可扩展性。

  • Java实现java.io包下的所有类,如InputStreamOutputStream的相关操作。

2.2 同步非阻塞I/O (NIO - Non-blocking I/O)

为了解决BIO的阻塞问题,应用程序可以通过系统调用将Socket设置为“非阻塞”模式。

  • 工作流程

    1. 应用程序发起一个非阻塞的read调用。

    2. 如果内核中的数据尚未准备好,read调用会立即返回一个错误码(EWOULDBLOCK),而不是阻塞线程。

    3. 应用程序可以不断地轮询(polling) 内核,重复发起read调用,询问数据是否就绪。

    4. 一旦某次轮询发现数据就绪了,内核就会将数据拷贝到用户空间,然后read调用成功返回。

  • 特点:应用程序线程在等待数据准备阶段是非阻塞的,可以去做其他任务。但轮询过程会耗费大量的CPU资源,因为大部分轮询调用都是无效的,空耗CPU cycles。

  • Java实现:通过SocketChannel.configureBlocking(false)设置非阻塞模式。

2.3 I/O多路复用 (I/O Multiplexing)

这是Java NIO的核心模型,也称为“事件驱动I/O”。它用一个系统调用(如selectpollepoll)来监听多个文件描述符(Socket)的读写事件。

  • 工作流程

    1. 应用程序首先将需要监听的Socket注册到一个多路复用器(Selector) 上,并关注感兴趣的事件(如读就绪、写就绪)。

    2. 应用程序调用Selector.select()方法,这个调用是阻塞的,直到有一个或多个被监听的Socket有事件就绪。

    3. select()返回后,应用程序会拿到一个事件集合,然后同步地、非阻塞地对这些就绪的Socket进行实际的I/O操作(如readwrite)。

  • 特点

    • 一个或少量线程可以管理大量的连接,极大地减少了线程资源消耗。

    • 它本质上是同步I/Oselect是阻塞的,实际的I/O操作也是应用程序自己完成的),而非异步I/O。

    • 避免了非阻塞I/O中无用的轮询,将轮询工作交给了内核,效率更高。

  • Java实现java.nio包中的SelectorChannelBuffer

2.4 异步I/O (AIO - Asynchronous I/O)

真正的异步I/O模型,由POSIX规范定义。

  • 工作流程

    1. 应用程序发起一个aio_read等异步调用,并提供一个缓冲区地址和回调函数,然后调用立即返回,应用程序线程继续执行其他任务。

    2. 内核会自己完成所有工作:等待数据准备、将数据从内核空间拷贝到用户空间缓冲区。

    3. 内核完成所有操作后,主动通知应用程序(通过信号或执行回调函数),告知I/O操作已经完成。

  • 特点

    • 应用程序从发起调用到收到结果,整个过程中都完全没有被阻塞

    • 与I/O多路复用的关键区别在于:数据拷贝的阶段也是由内核完成的,应用程序无需参与

  • Java实现java.nio.channels.AsynchronousChannel及相关类。

总结对比

模型 阶段一:等待数据准备 阶段二:数据从内核拷贝到用户 线程状态
同步阻塞 (BIO) 阻塞 阻塞 全程阻塞
同步非阻塞 (NIO) 非阻塞(轮询) 阻塞 拷贝阶段阻塞
I/O多路复用 (Java NIO) 阻塞在select调用 同步非阻塞地进行 select调用阻塞,I/O操作非阻塞
异步I/O (AIO) 不阻塞 不阻塞 全程无阻塞

三、Java NIO的几个核心组件是什么?分别有什么作用?

Java NIO由三大核心组件构成:Channel(通道)、Buffer(缓冲区)、Selector(选择器)。NIO是面向缓冲区通道来操作的。

3.1 Buffer (缓冲区)

  • 作用数据的临时存储容器,是所有I/O操作的起点和终点。应用程序与Channel之间的所有数据交换都必须通过Buffer进行。

  • 本质:本质上是一个数组,但提供了结构化访问数据的方法和读写状态的维护。

  • 关键属性

    • Capacity (容量):缓冲区最大数据容量,创建后不可改变。

    • Position (位置):下一个要被读或写的元素的索引。

    • Limit (上限):缓冲区中第一个不能被读或写的元素的索引。

    • Mark (标记):一个备忘位置,通过mark()方法标记一个位置,之后可以通过reset()方法回到这个位置。

  • 常用类型ByteBuffer(最常用), CharBufferIntBuffer等。

  • 工作模式flip()clear()rewind()等方法用于在读写模式间切换。

3.2 Channel (通道)

  • 作用连接数据源与数据汇(如文件、Socket)的管道,用于进行数据的读取和写入。它与Stream的不同之处在于:

    • Channel是双向的,可以用于读、写或同时读写,而Stream是单向的。

    • Channel总是配合Buffer一起使用,数据总是从Channel读到Buffer中,或者从Buffer写入到Channel中。

    • Channel支持异步非阻塞模式。

  • 主要实现

    • FileChannel:用于文件I/O。

    • SocketChannel & ServerSocketChannel:用于TCP网络I/O。

    • DatagramChannel:用于UDP网络I/O。

3.3 Selector (选择器)

  • 作用I/O多路复用的核心。一个Selector可以同时轮询多个Channel。当某个Channel上有它注册的事件(如连接接入、数据可读、数据可写)发生时,Selector就会将这些Channel筛选出来,通过SelectionKey告知应用程序,应用程序再对这些就绪的Channel进行相应的I/O操作。

  • 优势:使用单个(或少量)线程就可以管理成百上千的Channel,极大地提升了系统的连接容量和 scalability(可扩展性)。

  • 核心类

    • Selector:多路复用器本身。

    • SelectionKey:代表了Channel在Selector上的一个注册令牌。它包含了事件类型(OP_READOP_WRITEOP_CONNECTOP_ACCEPT)和与之关联的Channel和Selector。

工作流程简述

  1. 创建Selector:Selector selector = Selector.open();

  2. 将Channel设置为非阻塞模式,并注册到Selector上,关注感兴趣的事件:channel.register(selector, SelectionKey.OP_READ);

  3. 在一个循环中调用selector.select(),阻塞等待事件发生。

  4. 获取就绪的SelectionKey集合,迭代处理每一个事件。

  5. 根据事件类型,从SelectionKey中获取对应的Channel,进行I/O操作。


四、select,poll和epoll有什么区别?

selectpoll, 和 epoll 都是Linux系统下I/O多路复用的具体实现机制,它们是Java NIO中Selector在Linux平台的底层基石。它们的演进过程就是性能不断提升的过程。

4.1 select

  • 工作机制

    1. 应用程序告诉内核,它关心哪些文件描述符(fd)上的哪些事件(读、写、异常)。

    2. 内核通过线性扫描所有被监视的fd集合,来找出有事件就绪的fd。

    3. 每次调用select都需要将整个fd集合从用户空间拷贝到内核空间,调用返回后,又需要将整个fd集合从内核空间拷贝回用户空间。

  • 缺点

    1. fd数量限制:单个进程能监视的fd数量有最大限制(通常是1024)。

    2. 性能线性下降:每次调用都需要线性扫描整个fd集合,随着fd数量的增加,性能会线性下降。

    3. 内存拷贝开销大:每次调用都需要在用户态和内核态之间来回拷贝整个fd集合,开销很大。

4.2 poll

  • 工作机制poll的机制与select非常相似。主要区别在于它使用链表来存储fd,而不是select的数组。

  • 改进

    • 解决了fd数量限制问题:因为使用链表,理论上没有最大数量限制。

  • 遗留问题

    • 仍然需要线性扫描整个fd集合,性能问题依旧。

    • 仍然需要整体拷贝fd集合,开销问题依旧。

4.3 epoll (Linux 2.6+)

epoll是Linux下性能最优的多路复用机制,它完美地解决了selectpoll的问题。

  • 工作机制

    1. epoll_create: 创建一个epoll实例,在内核中开辟一个专用的空间来管理fd。

    2. epoll_ctl: 用于向epoll实例添加、修改或删除需要监听的fd及其事件。这个过程只需在初始化时或变更时调用一次,避免了每次调用时的重复拷贝

    3. epoll_wait: 等待事件的发生。调用时,它只返回那些真正有事件就绪的fd的信息给应用程序,而无需扫描整个fd集合

  • 核心优势

    1. 无fd数量限制:支持打开的fd数量远大于1024(上限是系统最大文件句柄数)。

    2. 高性能

      • 回调机制:内核通过在每个fd上注册的回调函数,当fd就绪时,将其加入一个就绪链表epoll_wait只需要查看这个就绪链表是否为空即可,时间复杂度是O(1)。

      • 避免了线性扫描,性能不会随着fd数量的增加而显著下降。

    3. 零拷贝epoll_ctl只在初始化时拷贝一次fd信息,之后epoll_wait调用只会将就绪的fd信息拷贝回用户空间,大大减少了内存拷贝的开销。

三者的区别总结表

特性 select poll epoll
数据结构 数组 链表 红黑树+就绪链表
最大连接数 有限制 (1024) 无限制 无限制
fd拷贝方式 每次调用select,全量拷贝 每次调用poll,全量拷贝 epoll_ctl注册时拷贝一次,epoll_wait不拷贝
工作效率 线性扫描所有fd,O(n) 线性扫描所有fd,O(n) 回调通知,O(1)
内核支持 几乎所有操作系统 几乎所有UNIX 主要是Linux

五、HTTP和HTTPS的区别

HTTP (HyperText Transfer Protocol) 和 HTTPS (HTTP Secure) 是应用层最广泛使用的协议,它们的核心区别在于安全性

5.1 核心区别:安全性

  • HTTP明文传输。请求和响应的报文内容全部以明文方式在网络上传播,不提供任何方式的数据加密。这意味着在传输过程中的任何一个环节(路由器、运营商、公共Wi-Fi等)都可能被窃听、篡改或冒充(中间人攻击)。

  • HTTPS加密传输。HTTPS = HTTP + SSL/TLS。它在HTTP之下加入了一个安全套接字层(SSL)或其继任者传输层安全协议(TLS)。通过SSL/TLS协议,对传输的数据进行加密身份认证,确保了通信的保密性、完整性和真实性

5.2 详细对比

对比维度 HTTP HTTPS
协议层 应用层协议,直接运行在TCP之上 运行在SSL/TLS之上,而SSL/TLS运行在TCP之上
默认端口 80 443
URL地址 http://... https://...
安全性 。明文传输,易被窃听和篡改 。加密传输,防止窃听;校验机制防止篡改;证书机制防止冒充
加密方式 采用混合加密机制:
非对称加密(如RSA)用于握手阶段交换对称加密的密钥
对称加密(如AES)用于加密实际传输的数据
散列算法(如SHA256)用于校验数据完整性
身份认证 通过数字证书(由可信的证书颁发机构CA签发)来验证服务器的身份,防止“中间人攻击”
性能与开销 无加密解密消耗,速度更快,资源消耗更少 有加密解密消耗,速度稍慢,CPU和内存资源占用更多(但随着硬件发展,差距已缩小)
SEO & 浏览器支持 现代浏览器(如Chrome)会将纯HTTP网站标记为“不安全” 搜索引擎(如Google)给予HTTPS网站更高的排名权重,浏览器显示安全锁图标

5.3 HTTPS的工作原理简述(SSL/TLS握手)

  1. ClientHello:客户端向服务器发送支持的SSL/TLS版本、加密套件列表和一个随机数。

  2. ServerHello:服务器选择双方都支持的版本和加密套件,并发送自己的数字证书和另一个随机数给客户端。

  3. 验证证书:客户端使用预置的CA公钥验证服务器证书的真实性和有效性。

  4. Premaster Secret:客户端生成一个预主密钥,用服务器证书中的公钥加密后发送给服务器。

  5. 生成会话密钥:服务器用自己的私钥解密得到预主密钥。客户端和服务器利用之前交换的两个随机数和这个预主密钥,独立计算出相同的对称加密会话密钥

  6. 加密通信:握手完成,双方使用生成的会话密钥进行对称加密的HTTP通信。

总结:

本文对 Java 中常见的几个核心概念进行了梳理与总结,旨在帮助读者更好地区分和理解相关机制。若存在表述不准确之处,欢迎指正与讨论。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐