• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

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

武飞扬头像
yfyh2021
帮助1

编程中的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();
     }
    

    }
    }

可以看到主线程启动,线程阻塞在了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();
    
     }
    
    学新通

    }
    }

我们在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 堆外内存相对来说,不适合存储很复杂的对象。一般简单的对象或者扁平化的比较适合。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcbhif
系列文章
更多 icon
同类精品
更多 icon
继续加载