java io模型 BIO NIO 使用

BIO

同步阻塞模型,指的是用户空间(或者线程)主动发起,需要等待内核 IO 操作彻底完成后才返回到用户空间的 IO 操作。在 IO 操作过程中,发起 IO 请求的用户进程(或者线程)处于阻塞状态。
代码示例:

public class SocketServer {

    public static void main(String[] args) throws IOException {

        ServerSocket serverSocket = new ServerSocket(8088);
        while (true) {
            // 等待连接 阻塞
            Socket socket = serverSocket.accept();
            //客户端连接
            System.out.println("客户端连接" +  socket.getPort());
            // 接受客户端消息
            byte[] bytes = new byte[1024];
            int read = socket.getInputStream().read(bytes);

            System.out.println("客户端发送消息:" + new String(bytes, 0, read));

            socket.getOutputStream().write("ok".getBytes());

            socket.getOutputStream().flush();
        }

    }
}

public class SocketClient {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost", 8088);
        socket.getOutputStream().write("hello".getBytes());
        socket.getOutputStream().flush();
        byte[] bytes = new byte[1024];
        int read = socket.getInputStream().read(bytes);
        System.out.println("服务端发送消息:" + new String(bytes, 0, read));
        socket.close();
    }
}

NIO

非阻塞IO + IO 多路复用模型,服务器实现模式为一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到多路复用器selector上,多路复用器轮询到连接有IO请求就进行处理。

服务端

public class NioServer {

    public static void main(String[] args) throws IOException {
        // 创建server
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 绑定端口
        serverSocketChannel.socket().bind(new InetSocketAddress(8088));
        // 设置非阻塞
        serverSocketChannel.configureBlocking(false);
        // 复用器
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            // 监听事件  会阻塞
            selector.select();
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                if (selectionKey.isAcceptable()) { // 客户端连接
                    ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();
                    SocketChannel accept = server.accept();
                    accept.configureBlocking(false);
                    // 注册读事件
                    accept.register(selector, SelectionKey.OP_READ);
                    System.out.println("客户端连接成功");
                } else if (selectionKey.isReadable()) { // 读事件
                    SocketChannel socket = (SocketChannel) selectionKey.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    int read = socket.read(byteBuffer);
                    if (read > 0) {
                        System.out.println("客户端发送消息:" + new String(byteBuffer.array(), 0 , read));
                    } else if (read == -1) {
                        System.out.println("客户端断开连接");
                        socket.close();
                    }
                    socket.write(ByteBuffer.wrap("ok".getBytes()));
                }
                iterator.remove();
            }
        }
    }
}

客户端

public class NioClient {

    public static void main(String[] args) throws IOException {

        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress("127.0.0.1", 8088));
        Selector selector = Selector.open();
        socketChannel.register(selector, SelectionKey.OP_CONNECT);

        while (true) {
            selector.select();
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                if (selectionKey.isConnectable()) {
                    SocketChannel channel = (SocketChannel) selectionKey.channel();
                    channel.configureBlocking(false);
                    // 正在连接
                    if (channel.isConnectionPending()) {
                        channel.finishConnect();
                    }
                    ByteBuffer buffer = ByteBuffer.wrap("HelloServer".getBytes());
                    channel.write(buffer);
                    channel.register(selector, SelectionKey.OP_READ);
                } else if (selectionKey.isReadable()) { // 读事件
                    SocketChannel socket = (SocketChannel) selectionKey.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    int read = socket.read(byteBuffer);
                    if (read > 0) {
                        System.out.println("服务端发送消息:" + new String(byteBuffer.array(), 0 , read));
                    } else if (read == -1) {
                        System.out.println("服务端断开连接");
                        socket.close();
                    }
                }
                iterator.remove();
            }
        }
    }
}

使用netty

Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。
服务端

public class NettyServer {

    public static void main(String[] args) throws InterruptedException {

        //连接处理线程
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        // 业务处理线程
        EventLoopGroup workGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workGroup)
                .channel(NioServerSocketChannel.class) // 使用nio管道
                .option(ChannelOption.SO_BACKLOG, 1024) // 设置客户端连接请求等待队列
                .childHandler(new ChannelInitializer<SocketChannel>() {//创建通道初始化对象,设置初始化参数

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        // 消息都是ByteBuf , 使用字符串
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast(new StringEncoder());
                        ch.pipeline().addLast(new NettyServerHandler());
                    }
                });
        //绑定端口
        ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();
        channelFuture.channel().closeFuture().sync();
    }
}

public class NettyServerHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        System.out.println("服务器接受到的消息:" + s);
    }
}

客户端

public class NettyClient {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception {
                        //加入处理器
                        channel.pipeline().addLast(new StringDecoder());
                        channel.pipeline().addLast(new StringEncoder());
                        channel.pipeline().addLast(new NettyClientHandler());
                    }
                });

        //启动客户端去连接服务器端
        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8088).sync();
        channelFuture.sync().channel().writeAndFlush("HelloServer");
        //对关闭通道进行监听
        channelFuture.channel().closeFuture().sync();
    }
}

public class NettyClientHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        System.out.println("客户端接受到的消息:" + s);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值