尚硅谷Netty系列学习笔记八《NIO快速入门》

目录

前言:

逻辑流程

逻辑图

代码

服务器代码示例

客户端代码示例

结语

下一篇:尚硅谷Netty系列学习笔记九《NIO搭建简易聊天室》


前言

结合之前的知识,深入理解下NIO非阻塞的网络编程原理,并写一个NIO的demo,demo包含了服务端和客户端

逻辑流程

1.创建NIO服务器通道ServerSocketChannel,监听端口8888,并设置为非阻塞模式,

2.创建Selector实例,并把ServerSocketChannel实例注册到Selector实例上,并监听连接事件

3.客户端连接,形成事件被Selector实例感知到后,通过ServerSocketChannel实例来建立连接,并给连接的客户端

    创建一个SocketChannel。

4.把给客户端创建的的SocketChannel实例同样注册到Selector实例上,监听读事件

5.客户端发送消息,被服务器端的Selector感知到,通过获取SelectionKey来获取对应事件的SocketChannel,并把通道数据读到缓冲区,打印到控制台!
 

逻辑图

代码

服务器代码示例



import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * NioServer
 */
public class NioServer {

    public static void main(String[] args) throws IOException {
        //创建 ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //绑定启动端口并启动
        serverSocketChannel.bind(new InetSocketAddress(8888));
        //设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //创建选择器
        Selector selector = Selector.open();
        //将 serverSocketChannel 注册到选择器上 关心的事件为 OP_ACCEPT(连接事件)
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            //这离我们等待1秒,如果没有事件发生,就返回 。也可以使用 selectNow() : 没有事件立刻返回。
            int select = selector.select(1000);
            if (select == 0) {
                System.out.println("没有事件发生");
                continue;
            }
            //selectedKeys 返回关注事件的集合
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = keys.iterator();
            //遍历
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (key.isAcceptable()) {
                    //发生 OP_ACCEPT(连接事件)
                    System.out.println("有一个客户端连接了");
                    //通过 serverSocketChannel创建 SocketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    //设置为非阻塞,否则不能注册到选择器中
                    socketChannel.configureBlocking(false);
                    //注册到 选择器中,关心的事件为 OP_READ(读),另外注册时绑定了一个 ByteBuffer 后续可直接 key.attachment() 获取该缓冲区对象
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }else if (key.isReadable()) {
                    //发生 OP_READ (读事件)
                    SocketChannel channel = (SocketChannel) key.channel();
                    ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
                    channel.read(byteBuffer);
                    System.out.println("客户端说:" + new String(byteBuffer.array()));
                }
                //手动从集合中删除 selectionKey
                keyIterator.remove();
            }
        }


    }
}

客户端代码示例


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

/**
 * NioClient
 */
public class NioClient {

    public static void main(String[] args) throws IOException {
        //创建一个客户端的SocketChannel
        SocketChannel socketChannel = SocketChannel.open();
        //设置非阻塞
        socketChannel.configureBlocking(false);
        //创建一个 InetSocketAddress 用于连接
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8888);
        //socketChannel.connect 连接到服务器,连接失败,会返回false,由于是非阻塞的,并且连接也需要时间,这里并不一定会立马连接成功
        if (!socketChannel.connect(inetSocketAddress)) {
            //finishConnect方法 检查连接是否成功,不成功可以先做别的事
            while (!socketChannel.finishConnect()) {
                System.out.println("连接需要时间,可以做其他的事情");
            }
        }
        String str = "hello world";

        //ByteBuffer.wrap 将字节数组包装到缓冲区中。字节数组多大,创建的缓冲区就多大,主要是使用方便!
        ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());
        socketChannel.write(byteBuffer);
        //让客户端停在这
        System.in.read();

    }
}

结语

先启动服务器,再启动客户端,控制台打印如下:

下一篇:尚硅谷Netty系列学习笔记九《NIO搭建简易聊天室》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值