栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

BIO与NIO的简单介绍

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

BIO与NIO的简单介绍

BIO

流程:
● 在服务端创建ServerSocket server用于监听访问服务端8090端口的请求
● 在主线程中,server.accept()处会发生阻塞,一直阻塞到server.accept()成功返回数据(有个客户端对服务端8090端口发起了访问请求)。一旦server.accept()成功返回socket,意味着该socket成功与客户端建立起了连接。
● 接下来需要接收客户端发的数据,但是如果客户端一直不发数据,那么程序也会在这里阻塞,下一个client会进不来。于是抛出一个线程,不论客户端有没有发数据,程序都会继续往下运行。下一个client会有新的对应socket和线程。
● BIO的这种特性被称为“每线程,每连接”。优势是可以接收很多连接,劣势是线程内存浪费,CPU调度消耗。

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.linkedList;

public class NIOSocket {

    public static void main(String[] args) throws Exception{
        linkedList clients = new linkedList<>();

        ServerSocketChannel ss = ServerSocketChannel.open();
        ss.bind(new InetSocketAddress(9090));
        ss.configureBlocking(false);  // 重点,设置成了非阻塞

        while (true) {
            Thread.sleep(1000);
            SocketChannel client = ss.accept();  // 这里不会阻塞,如果真的有客户端来请求,则返回客户端;如果没有,则返回null

            if (client == null) {
                System.out.println("null");
            } else {
                client.configureBlocking(false);  // 重点,设置成了非阻塞
                int port = client.socket().getPort();
                System.out.println("client...port: "+port);
                clients.add(client);
            }

            ByteBuffer buffer = ByteBuffer.allocateDirect(4096);

            // 遍历已有的客户端看有没有发数据
            for (SocketChannel c: clients) {
                int num = c.read(buffer);
                if (num > 0) {
                    buffer.flip();
                    byte[] aaa = new byte[buffer.limit()];
                    buffer.get(aaa);

                    String b = new String(aaa);
                    System.out.println(c.socket().getPort()+":"+b);
                    buffer.clear();
                }
            }

        }
    }
}
NIO

NIO的思路就是,把BIO中会引起阻塞的两个地方都给改成了非阻塞,所以不再需要一堆的线程了,一个线程就可以了。
● 优点:避开了多线程导致的问题
● 缺点:如果连接数特别大,比如有一万个连接client,但是只有一两个在发数据,那么每次循环都要往内核发一万次请求,就会极大的浪费时间和资源(用户空间向内核空间的循环遍历,复杂度在系统调用上)。

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.linkedList;

public class NIOSocket {

    public static void main(String[] args) throws Exception{
        linkedList clients = new linkedList<>();

        ServerSocketChannel ss = ServerSocketChannel.open();
        ss.bind(new InetSocketAddress(9090));
        ss.configureBlocking(false);  // 重点,设置成了非阻塞

        while (true) {
            Thread.sleep(1000);
            SocketChannel client = ss.accept();  // 这里不会阻塞,如果真的有客户端来请求,则返回客户端;如果没有,则返回null

            if (client == null) {
                System.out.println("null");
            } else {
                client.configureBlocking(false);  // 重点,设置成了非阻塞
                int port = client.socket().getPort();
                System.out.println("client...port: "+port);
                clients.add(client);
            }

            ByteBuffer buffer = ByteBuffer.allocateDirect(4096);

            // 遍历已有的客户端看有没有发数据
            for (SocketChannel c: clients) {
                int num = c.read(buffer);
                if (num > 0) {
                    buffer.flip();
                    byte[] aaa = new byte[buffer.limit()];
                    buffer.get(aaa);

                    String b = new String(aaa);
                    System.out.println(c.socket().getPort()+":"+b);
                    buffer.clear();
                }
            }

        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/319071.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号