• 网络通信编程基础,BIO,NIO


    编程中的Socket是什么?
    Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,其实就是一个门面模式。

    BIO的阻塞提现在两个方面

    1. 若一个服务器启动就绪,那么服务器的主线程就一直等待着客户端连接,这个等待过程中主线程就在阻塞。
      public class ServerSingle {
      public static void main(String[] args) throws IOException {
      ServerSocket serverSocket = new ServerSocket();
      serverSocket.bind(new InetSocketAddress(8888));
      System.out.println(“Start Server …”);
      int connectCount = 0;
      try {
      while (true){
      Socket socket = serverSocket.accept();

               System.out.println("accept client socket ....total =" + ( ++connectCount));
               ObjectInputStream inputStream =
                       new ObjectInputStream(socket.getInputStream());
               ObjectOutputStream outputStream =
                       new ObjectOutputStream(socket.getOutputStream());
               String userName = inputStream.readUTF();
               System.out.println("Accept client message:"+userName);
               outputStream.writeUTF("Hello,"+userName);
               outputStream.flush();
           }
       }catch (Exception e){
           e.printStackTrace();
       }finally {
          serverSocket.close();
       }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

      }
      }

    可以看到主线程启动,线程阻塞在了accept()监听方法,后面的没有打印

    1. 在连接建立之后,在读到socket信息之前,线程也是一直在等待的,阻塞在那里。
      public class Client {
      public static void main(String[] args) throws IOException {
      Socket socket = null;
      ObjectOutputStream output = null;
      ObjectInputStream input = null;
      InetSocketAddress addr
      = new InetSocketAddress(“127.0.0.1”,8888);

       try {
           socket = new Socket();
           socket.connect(addr);
           System.out.println("Connect Server success!!");
           output = new ObjectOutputStream(socket.getOutputStream());
           input = new ObjectInputStream(socket.getInputStream());
           System.out.println("Ready send message.....");
           output.writeUTF("yang");
           output.flush();
           System.out.println(input.readUTF());
       } catch (IOException e) {
           e.printStackTrace();
       }finally {
           if (socket!=null) socket.close();
           if (output!=null) output.close();
           if (input!=null) input.close();
      
       }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

      }
      }

    我们在client中打上断点,debug启动。可以看到client连接成功,server端的accept也接收到了,但是主线程又阻塞在了等待socket的输出当中

    NIO和BIO的主要区别

    1. NIO和IO的主要区别是IO是面向流的,而NIO是面向缓冲区的。
    2. 阻塞与非阻塞

    NIO三大核心组件

    1. Selector。记录发生的事件,以及服务端和客户端关注的事件。
    2. channel。本质上就是socket的包装类。分为serverSocketChannel和socketChannel,serverSocketChannel只关心accept的事件,也只有服务端才会关心;而socketChannel就是普通的socket关心读写事件。客户端的socketChannel关心connect事件。
    3. buffer。缓冲区,我们上面说到NIO是面向缓冲区的,就是这个buffer,就是因为buffer的存在,使得线程不需要等待。

    重要概念:SelectionKey
    SelectionKey是一个抽象类,表示selectableChannel在Selector中注册的标识,其中有四种状态分别是OP_READ(读事件),OP_WRITE(写事件),OP_CONNECT(发起连接事件),OP_ACCEPT(接收连接事件)

    直接内存比堆内存快在哪
    jvm在向socket缓冲区发送信息时,会在堆外重新开辟一块内存,将要发送的信息拷贝进去。这样做的原因是防止在gc的时候,改变堆内信息的位置。

    堆外内存的优点和缺点
    堆外内存相比于堆内内存有几个优势:
    1 减少了垃圾回收的工作,因为垃圾回收会暂停其他的工作(可能使用多线程或者时间片的方式,根本感觉不到)
    2 加快了复制的速度。因为堆内在flush到远程时,会先复制到直接内存(非堆内存),然后在发送;而堆外内存相当于省略掉了这个工作。
    而福之祸所依,自然也有不好的一面:
    1 堆外内存难以控制,如果内存泄漏,那么很难排查
    2 堆外内存相对来说,不适合存储很复杂的对象。一般简单的对象或者扁平化的比较适合。

  • 相关阅读:
    2023人机交互期末复习
    初探CSS 上
    【学习笔记】最短路 +生成树
    Spring AOP快速入门----XML方式和注解方式
    主流嵌入式操作系统有哪些
    学习笔记|IO中断|中断号大于31|中断优先级|简易中央门禁|STC32G单片机视频开发教程(冲哥)|第十六集:IO中断
    destoon 调用第三方api接口
    8位二进制cpu的设计和制作(三)
    《网络协议》07. 其他协议
    FFmpeg日志系统、文件与目录、操作目录
  • 原文地址:https://blog.csdn.net/yfyh2021/article/details/126052426