Java IO 模型(3)

Java IO 模型

3.7 NIO 群聊

3.7.1 效果图

server
在这里插入图片描述

client
在这里插入图片描述

3.7.2 server coding

public class NioServer {

    private static final String HOST = "127.0.0.1";
    private static final int PORT = 9099;

    private Selector selector;
    private ServerSocketChannel serverSocketChannel;

    public NioServer() {

        try {

            // 创建 selector
            selector = Selector.open();

            // 开启 serverSocketChannel
            serverSocketChannel = ServerSocketChannel.open();

            // 绑定端口
            serverSocketChannel.socket().bind(new InetSocketAddress(HOST, 9099));

            // 设置为非阻塞模式
            serverSocketChannel.configureBlocking(false);

            // 将 serverSocketChannel 注册到 selector
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (Exception e) {
            System.out.println("server 端启动异常");
            e.printStackTrace();
        }

    }

    public void listen() {

        try {
            while (true) {

                // 等待事件处理
                if (selector.select() == 0) {
                    System.out.println("等待 client 连接....");
                    continue;
                }

                // 处理连接的 client

                // 获取所有连接的 client 事件
                Set<SelectionKey> selectionKeys = selector.selectedKeys();

                Iterator<SelectionKey> iterator = selectionKeys.iterator();

                // 遍历事件
                while (iterator.hasNext()) {

                    SelectionKey key = iterator.next();

                    // 处理 accept 事件
                    if (key.isAcceptable()) handlerAccept(key);

                    // 处理 read 事件
                    if (key.isReadable()) handlerRead(key);

                    // 移除处理完的 channel
                    iterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void handlerAccept(SelectionKey key) {

        try {
            System.out.println("server 端处理 accept 事件...");

            SocketChannel channel = serverSocketChannel.accept();

            channel.configureBlocking(false);

            channel.register(selector, SelectionKey.OP_READ);

            System.out.println(channel.getRemoteAddress() + " 机器已经上线");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    private void handlerRead(SelectionKey key) {


        SocketChannel channel = null;

        try {
            System.out.println("server 处理 read 事件...");

            channel = (SocketChannel) key.channel();

            ByteBuffer buffer = ByteBuffer.allocate(1024);

            int read = channel.read(buffer);

            if (read > 0) {

                String msg = new String(buffer.array(), StandardCharsets.UTF_8);

                System.out.println("收到来自 " + channel.getRemoteAddress() + " 的消息 msg = " + msg);

                // 讲消息发送给其他 client 端
                sendOtherClient(channel, msg);

            }
        } catch (IOException e) {

            if (channel != null) {
                try {
                    System.out.println(channel.getRemoteAddress() + " 机器下线 ....");
                    // 取消注册 关闭通道
                    key.cancel();
                    channel.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

        }

    }

    private void sendOtherClient(SocketChannel selfChannel, String msg) throws IOException {

        System.out.println("server 正在转发 " + selfChannel.getRemoteAddress() + " 机器的消息.......");

        for (SelectionKey key : selector.keys()) {

            SelectableChannel channel = key.channel();

            if (channel instanceof SocketChannel && channel != selfChannel) {

                SocketChannel ch = (SocketChannel) channel;

                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));

                ch.write(buffer);

                System.out.println("server 将 " + selfChannel.getRemoteAddress() + " 的消息转发给 " + ch.getRemoteAddress());

            }

        }

    }


    public static void main(String[] args) {

        System.out.println("server running........");

        NioServer server = new NioServer();

        server.listen();

    }

}

3.7.3 client coding

public class NioClient {

    private static final String HOST = "127.0.0.1";
    private static final int PORT = 9099;

    private Selector selector;
    private SocketChannel socketChannel;

    public NioClient() {

        try {
            selector = Selector.open();

            socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT));

            socketChannel.configureBlocking(false);

            socketChannel.register(selector, SelectionKey.OP_READ);

            System.out.println(socketChannel.getLocalAddress() + " id ok...");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void handlerRead() {

        try {

            int select = selector.select();

            if (select > 0) {

                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();

                while (iterator.hasNext()) {

                    SelectionKey key = iterator.next();

                    if (key.isReadable()) {

                        SocketChannel channel = (SocketChannel) key.channel();

                        ByteBuffer buffer = ByteBuffer.allocate(1024);

                        channel.read(buffer);

                        String msg = new String(buffer.array(), StandardCharsets.UTF_8);

                        System.out.println("client read msg : " + msg.trim());

                    }

                    iterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void send(String msg) {

        try {
            msg = socketChannel.getLocalAddress() + " 发出的数据 " + msg;

            socketChannel.write(ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8)));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {

        System.out.println("client running...");

        NioClient client = new NioClient();

        new Thread(() -> {
            while (true) {
                client.handlerRead();
            }
        }).start();


        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNextLine()) {
            client.send(scanner.nextLine());
        }


    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值