• 网络通信编程基础,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 堆外内存相对来说,不适合存储很复杂的对象。一般简单的对象或者扁平化的比较适合。

  • 相关阅读:
    SpringBoot整合Hive(开启Kerberos认证)作三方数据源
    Intel Cyclone 10 GX 收发器的初步认识
    Latex常用数学字符汇总
    柯桥英语培训,商务英语学习,常用口语
    Selenium+Python系列(一) - 开发环境搭建
    【python实战】朋友因股票亏了,很惨常愤恨不平,当天我就分析出原因:怎么做到的?(听说关注我的人会暴富)
    记一次用dataframe进行数据清理
    机器人C++库(2)Robotics Library API介绍
    Master PDF Editor v5 解锁版安装教程(小巧多功能PDF )
    ARINC825规范简介
  • 原文地址:https://blog.csdn.net/yfyh2021/article/details/126052426