温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java中怎么实现BIO阻塞式网络编程

发布时间:2021-06-30 17:24:16 来源:亿速云 阅读:137 作者:Leah 栏目:大数据

这篇文章将为大家详细讲解有关Java中怎么实现BIO阻塞式网络编程,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

阻塞IO的含义

阻塞(blocking)IO :阻塞是指结果返回之前,线程会被挂起,函数只有在得到结果之后(或超时)才会返回

非阻塞(non-blocking)IO :非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回

同步(synchronous)IO :应用阻塞在发送或接受数据的状态,直至数据成功传输(或返回失败),简单来说就是必须一件一件事做,等前一件做完了才能做下一件事

异步(asynchronous)IO :应用发送或接受数据后立即返回,实际处理这个调用的程序在完成后,通过状态、通知和回调来通知调用者

阻塞和非阻塞是获取资源的方式,同步和异步是程序如何处理资源的逻辑。

BIO网络编程

首先我们来看一段最基础的Java网络编程代码示例:

服务器端代码示例:

public class BIOServerV1 {
  public static void main(String[] args) throws Exception {
    ServerSocket serverSocket = new ServerSocket(8080);
    System.out.println("服务器启动成功");
    while (!serverSocket.isClosed()) {

      Socket request = serverSocket.accept(); // 阻塞

      System.out.println("收到新连接:" + request.toString());

      try {
        InputStream inputStream = request.getInputStream(); // 获取数据流        BufferedReader bufferedReader =
            new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
        String message;
        while ((message = bufferedReader.readLine()) != null) {
          if (message.length() == 0) {
            break;
          }
          System.out.println("消息内容为:" + message);
        }
        System.out.println("收到数据,来自:" + request.toString());
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        request.close();
      }
    }
    serverSocket.close();
  }
}

客户端代码示例:

public class BIOClient {
  public static void main(String[] args) throws IOException {
    Socket socket = new Socket("localhost", 8080);
    OutputStream outputStream = socket.getOutputStream();
    Scanner scanner = new Scanner(System.in);
    System.out.println("请输入:");
    String message = scanner.nextLine();
    outputStream.write(message.getBytes(Charset.forName("UTF-8")));
    scanner.close();
    socket.close();
  }
}

这个版本服务器端的代码同一时刻只能支持一个网络连接,在建立连接之后服务端线程会被阻塞,只有在已建立连接的客户端处理完数据关闭连接之后,后续的连接请求才能一个一个的处理,而为了能并发的处理多个请求我们在下一个版本中加入多线程的代码。

public class BIOServerV2 {
  private static ExecutorService executorService = Executors.newCachedThreadPool();
  public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket(8080);
    System.out.println("服务器启动成功");
    while (!serverSocket.isClosed()) {
      Socket request = serverSocket.accept();
      System.out.println("收到新连接:" + request.toString());

      // 多线程接收多个连接
      executorService.submit(
          () -> {
            try {
              InputStream inputStream = request.getInputStream();
              BufferedReader bufferedReader =
                  new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
              String message;
              while ((message = bufferedReader.readLine()) != null) {
                if (message.length() == 0) {
                  break;
                }
                System.out.println("消息内容为:" + message);
              }
              System.out.println("收到数据,来自:" + request.toString());
            } catch (IOException e) {
              e.printStackTrace();
            } finally {
              try {
                request.close();
              } catch (IOException e) {
                e.printStackTrace();
              }
            }
          });
    }
    serverSocket.close();
  }
}

这个版本的代码在加入多线程后可以并发的处理多个连接,但是它只能处理Java客户端的连接不能处理浏览器端的连接,而为了能与浏览器端交互我们需要了解HTTP协议的内容。

HTTP协议

HTTP协议请求数据包解析

Java中怎么实现BIO阻塞式网络编程

HTTP协议响应数据包解析

Java中怎么实现BIO阻塞式网络编程

HTTP协议响应状态码:

Java中怎么实现BIO阻塞式网络编程

BIO网络编程处理浏览器请求

在了解了HTTP协议的内容之后我们就可以依据HTTP协议的内容编写程序来处理浏览器请求。在之前多线程版本的代码之上我们需要对数据根据HTTP协议的内容进行处理,代码示例如下:

public class BIOServerV3 {
  private static ExecutorService executorService = Executors.newCachedThreadPool();
  public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket(8080);
    System.out.println("服务器启动成功");
    while (!serverSocket.isClosed()) {
      Socket request = serverSocket.accept();
      System.out.println("收到新连接:" + request.toString());

      // 多线程接收多个连接
      executorService.submit(
          () -> {
            try {
              InputStream inputStream = request.getInputStream();
              BufferedReader bufferedReader =
                  new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
              String message;
              while ((message = bufferedReader.readLine()) != null) {
                if (message.length() == 0) {
                  break;
                }

                // 拿到消息后可以解析消息拿到请求方法,请求数据等内容
                System.out.println("消息内容为:" + message);

              }
              System.out.println("收到数据,来自:" + request.toString());

              // 根据HTTP协议响应数据包返回数据给浏览器
              OutputStream outputStream = request.getOutputStream();
              outputStream.write("HTTP/1.1 200 OK\r\n".getBytes());
              outputStream.write("Content-Length: 11\r\n\r\n".getBytes());
              outputStream.write("Hello World".getBytes());
              outputStream.flush();
            } catch (IOException e) {
              e.printStackTrace();
            } finally {
              try {
                request.close();
              } catch (IOException e) {
                e.printStackTrace();
              }
            }
          });
    }
    serverSocket.close();
  }
}

关于Java中怎么实现BIO阻塞式网络编程就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI