JavaIO进阶系列——NIO模拟群聊系统day2-1

181 篇文章 3 订阅
21 篇文章 1 订阅

JavaIO进阶系列——NIO模拟群聊系统day2-1

NIO模拟群聊系统

Server

package test.chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

public class Server {
    //定义通道
    private ServerSocketChannel serverSocketChannel;
    //定义选择器
    private Selector selector;
    //定义端口
    private static final int PORT = 9000;

    public Server() {
        try {
            //创建选择器
            selector = Selector.open();
            //获取通道
            serverSocketChannel = ServerSocketChannel.open();
            //绑定端口
            serverSocketChannel.bind(new InetSocketAddress(PORT));
            //设置非阻塞模式
            serverSocketChannel.configureBlocking(false);
            //注册通道到选择器中
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //开始监听
    private void listen() {
        try {
            while (selector.select() > 0) {
                //获取所有就绪事件
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                //遍历事件
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    if (selectionKey.isAcceptable()) {
                        //获取通道
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        //设置非阻塞
                        socketChannel.configureBlocking(false);
                        //注册选择器
                        socketChannel.register(selector, SelectionKey.OP_READ);

                    } else if (selectionKey.isReadable()) {
                        //实现读取方法
                        this.readClient(selectionKey);
                    }
                    iterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //读取客户端消息,转发给所有其他的客户端通道
    private void readClient(SelectionKey selectionKey) throws IOException {
        SocketChannel socketChannel = null;
        try {
            //得到当前客户端通道
            socketChannel = (SocketChannel) selectionKey.channel();
            //创建缓冲区,接收数据
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int len = socketChannel.read(buffer);
            if (len > 0) {
                buffer.flip();
                String msg = new String(buffer.array(), 0, buffer.remaining());
                System.out.println(msg);
                //推送到所有客户端
                this.sendToALlClient(msg, socketChannel);
            }
        } catch (Exception e) {
            System.out.println(socketChannel.getRemoteAddress() + "下线了");
            //客户端离线
            //取消监听
            selectionKey.cancel();
            //关闭通道
            socketChannel.close();
        }
    }

    //推送到所有客户端
    private void sendToALlClient(String msg, SocketChannel socketChannel) throws IOException {
        System.out.println("开始转发:" + Thread.currentThread().getName());
        for (SelectionKey key : selector.keys()) {
            Channel channel = key.channel();
            //去除自己当前的通道
            //!(channel == socketChannel)
            if (channel instanceof SocketChannel && channel != socketChannel) {
                //封装后发送
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));
                ((SocketChannel) channel).write(buffer);
            }
        }
    }

    public static void main(String[] args) {
        Server server = new Server();
        server.listen();
    }
}

Client

package test.chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Scanner;

public class Client {
    //定义通道
    private SocketChannel socketChannel;
    //定义选择器
    private Selector selector;
    //端口
    private static final int PORT = 9000;


    public Client() {
        try {
            selector = Selector.open();
            socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", PORT));
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
            System.out.println("====Client ready:");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //读取信息
    public void readInfo() throws IOException {
        while (selector.select() > 0) {
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                if (selectionKey.isReadable()) {
                    SocketChannel channel = (SocketChannel) selectionKey.channel();
                    //读数据
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    channel.read(buffer);
                    System.out.println(new String(buffer.array()).trim());
                }
                iterator.remove();
            }
        }
    }

    public static void main(String[] args) {
        Client client = new Client();
        new Thread(() -> {
            try {
                client.readInfo();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {

            String str = scanner.nextLine();
            client.sendToServer(str);
        }
    }

    //发送消息到客户端
    private void sendToServer(String str) {
        try {
            socketChannel.write(ByteBuffer.wrap(("client:" + str).getBytes(StandardCharsets.UTF_8)));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值