nio聊天室-netty学习之旅

1.服务器使用nio的方式

1.1定义成员变量

    private ServerSocketChannel serverSocketChannel;
    private ServerSocket serverSocket;
    private Selector selector;

1.2定义构造函数,进行配置初始化

    public GroupChatServer() throws IOException {
        // 开启一个serverSocketChannel
        serverSocketChannel = ServerSocketChannel.open();
        // 设置通道为非阻塞模式
        serverSocketChannel.configureBlocking(false);
        // 创建serverSocket,绑定端口
        serverSocket = serverSocketChannel.socket();
        serverSocket.bind(new InetSocketAddress("127.0.0.1", 6666));
        // 初始化selector
        selector = Selector.open();
        // 将通道注册到selector并进行连接事件的监听
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    }

1.3监听事件,事件派发

    private  void listen() throws IOException {

        while (true) {
            if (selector.select(3000) <= 0) {
                System.out.println("未感触到信息");
            } else {
                System.out.println("感触到信息");
                Set<SelectionKey> keys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = keys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    if (key.isAcceptable()) {
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        // 通道设置为非阻塞,没数据读,不用阻塞
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                        SocketAddress address = socketChannel.getRemoteAddress();
                        System.out.println("主机为" + address + "的主机已经连接进来了");
                    } else if (key.isReadable()) {
                        SocketChannel channel = (SocketChannel) key.channel();
                        channel.configureBlocking(false);
                        //读取数据
                        readData(channel);
                    }
                    // 删除key,防止重复
                    iterator.remove();
                }
            }
        }
    }

1.4读取和转发的具体实现

    private void readData(SocketChannel channel) throws IOException {
        ByteBuffer byteBuffer = ByteBuffer.allocate(64);
        int read = channel.read(byteBuffer);
        if (read > 0) {
            String msg = new String(byteBuffer.array());
            System.out.println("服务接受到了来自主机:"+channel.getRemoteAddress()+"的消息:"+msg);
            // 进行消息转发
            sendInfoToOthers(msg, channel);
        }
    }

    private void sendInfoToOthers(String msg, SocketChannel channel) throws IOException {
        Set<SelectionKey> keys = selector.keys();
        for (SelectionKey key : keys) {
            Channel targetChannel =  key.channel();
            //key.
            //排除自己
            if (targetChannel instanceof SocketChannel &&targetChannel != channel) {
                SocketChannel dest = (SocketChannel)targetChannel;
                //将msg 存储到buffer
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                //将buffer 的数据写入 通道
                dest.write(buffer);
            }
        }
    }

1.5主函数

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

2.客户端写法,客户端用传统bio

2.1成员变量

    Socket socket = null;
    final static CountDownLatch cdl = new CountDownLatch(2);//参数为线程个数

2.2构造函数

    public GroupChatClient() throws IOException {
        socket = new Socket();
        socket.connect(new InetSocketAddress("127.0.0.1", 6666));
    }

2.3客户端处理逻辑主体

    public void chat() {
        if (socket.isConnected()) {
            new Thread(() -> {
                try {
                    while (true) {

                    readData();


                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                cdl.countDown();
            }).start();//用于读

            new Thread(() -> {
                try {
                    while (true) {
                        Scanner in = new Scanner(System.in);
                        String msg = in.next();

                        writeData(msg);

                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                cdl.countDown();
            }).start();//用于写
        }
    }

2.4读写

    public void readData() throws IOException {
        InputStream inputStream = socket.getInputStream();
        byte[] b = new byte[1024];
        int read = inputStream.read(b);
        if (read > 0) {
            System.out.println(new String(b));
        }
    }

    public void writeData(String msg) throws IOException {
        OutputStream outputStream = socket.getOutputStream();
        byte[] bytes = msg.getBytes();
        outputStream.write(bytes);
        System.out.println("成功写入");
    }

2.5主函数

    public static void main(String[] args) throws IOException, InterruptedException {
        GroupChatClient groupChatClient = new GroupChatClient();
        groupChatClient.chat();
        cdl.await();

    }

3.效果

3.1两客户端连接服务器成功

在这里插入图片描述

3.2转发效果

客户端1进行消息发送
在这里插入图片描述
服务端接受效果
在这里插入图片描述
客户端2接受效果
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值