【面试突击】网络通信面试实战

发布时间:2024年01月19日

🌈🌈🌈🌈🌈🌈🌈🌈
欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!

在我后台回复 「资料」 可领取编程高频电子书
在我后台回复「面试」可领取硬核面试笔记

文章导读地址:点击查看文章导读!

感谢你的关注!

🍁🍁🍁🍁🍁🍁🍁🍁

网络通信面试实战

Socket 工作原理

Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口,其实就是一个门面模式,将底层复杂的通信操作给封装起来对外提供接口。

简单来说就是 Socket 把 TPC/IP 协议给封装了起来,我们的程序进行网络通信都是通过 Socket 来完成的!

也就是说当两台设备进行通信时,是通过 Socket 进行通信的,接下来通过 Java 代码来了解一下如何通过 Socket 进行网络通信:

服务端:

public class Server {
    public static void main(String[] args) {
        int port = 1234; // 服务器监听的端口号

        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("服务器启动,等待客户端连接...");

            // 等待客户端连接
            Socket clientSocket = serverSocket.accept();
            System.out.println("客户端已连接:" + clientSocket.getInetAddress().getHostAddress());

            // 获取输入流
            InputStream input = clientSocket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));

            // 读取客户端发送的消息
            String received = reader.readLine();
            System.out.println("接收到消息: " + received);

            // 获取输出流
            OutputStream output = clientSocket.getOutputStream();
            PrintWriter writer = new PrintWriter(output, true);

            // 回显客户端发送的消息
            writer.println("服务器回显: " + received);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端:

public class Client {
    public static void main(String[] args) {
        String serverAddress = "localhost"; // 服务器地址
        int port = 1234; // 服务器监听的端口号

        try (Socket socket = new Socket(serverAddress, port)) {
            System.out.println("连接到服务器...");

            // 获取输出流
            OutputStream output = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(output, true);

            // 向服务器发送消息
            writer.println("Hello, Server!");

            // 获取输入流
            InputStream input = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));

            // 读取服务器回显的消息
            String response = reader.readLine();
            System.out.println("接收到服务器的回显: " + response);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BIO、NIO和AIO

面试中问到网络相关的内容,其中 BIO、NIO 的内容肯定是必问的,AIO 可以了解一下,一定要清楚 BIO 和 NIO 中通信的流程

我也画了两张图,可以记下这两张图

  • AIO:

从 Java.1.7 开始,Java 提供了 AIO(异步IO),Java 的 AIO 也被称为 “NIO.2”

Java AIO 采用订阅-通知模式,应用程序向操作系统注册 IO 监听,之后继续做自己的事情,当操作系统发生 IO 事件并且已经准备好数据时,主动通知应用程序,应用程序再进行相关处理

(Linux 平台没有这种异步 IO 技术,而是使用 epoll 对异步 IO 进行模拟)

  • BIO:

BIO 即同步阻塞 IO,服务端实现模式为一个连接对应一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理

BIO简单工作流程:

  1. 服务器端启动一个 ServerSocket,用于接收客户端的连接
  2. 客户端启动 Socket 与服务器建立连接,默认情况下服务器端需要对每个客户端建立一个线程与之通讯(并且与每一个可u后端有一个对应的 Socket)
  3. 客户端发出请求后, 先咨询服务器是否有线程响应,如果没有则会等待,或者被拒绝
  4. 如果服务端有对应线程处理
    • 客户端进行读取,则线程会被阻塞直到完成读取
    • 客户端进行写入,则线程会被阻塞直到完成写入

使用 BIO 通信的流程图如下:

在这里插入图片描述

BIO存在问题:

  1. 当并发量较大时,需要创建大量线程来处理连接,比较占用系统资源
  2. 连接建立之后,如果当前线程暂时没有数据可读,则线程会阻塞在 Read 操作上,造成线程资源浪费
  • NIO:

从 Java1.4 开始,Java 提供了 NIO,NIO 即 “Non-blocking IO”(同步非阻塞IO)

NIO 的几个核心概念:

  1. Channel、Buffer:BIO是基于字节流或者字符流的进行操作,而NIO 是基于缓冲区通道进行操作的,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中

  2. Selector:选择器用于监听多个通道的事件(如,连接打开,数据到达),因此,单个线程可以监听多个数据通道,极大提升了单机的并发能力

    当 Channel 上的 IO 事件未到达时,线程会在 select 方法被挂起,让出 CPU 资源,直到监听到 Channel 有 IO 事件发生,才会进行相应的处理

  • NIO和BIO有什么区别?
  1. NIO是以的方式处理数据,BIO是以字节流或者字符流的形式去处理数据。
  2. NIO是通过缓存区和通道的方式处理数据,BIO是通过InputStream和OutputStream流的方式处理数据。
  3. NIO的通道是双向的,BIO流的方向只能是单向的。
  4. NIO采用的多路复用的同步非阻塞IO模型,BIO采用的是普通的同步阻塞IO模型。
  5. NIO的效率比BIO要高,NIO适用于网络IO,BIO适用于文件IO。

NIO如何实现了同步非阻塞?

通过 Selector 和 Channel 来进行实现,一个线程使用一个 Selector 监听多个 Channel 上的 IO 事件,通过配置监听的通道Channel为非阻塞,那么当Channel上的IO事件还未到达时,线程会在select方法被挂起,让出CPU资源。直到监听到Channel有IO事件发生时,才会进行相应的响应和处理。

使用 NIO 通信的流程图如下:

在这里插入图片描述

文章来源:https://blog.csdn.net/qq_45260619/article/details/135689689
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。