文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java NIO实现聊天系统

2024-04-02 19:55

关注

使用Java的NIO写的一个小的聊天系统,供大家参考,具体内容如下

一、服务端



public class GroupChatServer {

    // 定义相关的属性
    private Selector selector;
    private ServerSocketChannel listenChannel;
    private static final int port = 6667;

    // 构造器
    // 进行初始化的操作
    public GroupChatServer() {
        try {
            // 获取选择器
            selector = Selector.open();
            // 获取到 listenChannel
            listenChannel = ServerSocketChannel.open();
            // 设定端口
            listenChannel.bind(new InetSocketAddress(port));
            // 设定非阻塞模式
            listenChannel.configureBlocking(false);
            // 将该 listenChannel 注册到 selector上 完成操作
            listenChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("服务器启动了。。。。");
        } catch (IOException e) {

        }

    }

    // 监听的代码

    public void listen() {
        try {
            // 循环处理
            while (true) {
                int count = selector.select(2000);
                if (count > 0) {
                    // 有事件需要处理
                    // 遍历处理 得到selectionKeys集合
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
                    while (selectionKeyIterator.hasNext()) {
                        // 得到selectionKey
                        SelectionKey selectionKey = selectionKeyIterator.next();
                        // 监听到了 accept
                        if (selectionKey.isAcceptable()) {
                            // 获取到连接
                            SocketChannel sc = listenChannel.accept();
                            sc.configureBlocking(false);
                            sc.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                            // 提示上线
                            System.out.println(sc.getRemoteAddress() + ":上线啦。。。。");
                        }

                        if (selectionKey.isReadable()) {
                            // 读取事件 通道是可以读的状态 //专门写
                            readData(selectionKey);
                        }


                        // 移除当前的删除 防止重复处理操作
                        selectionKeyIterator.remove();
                    }


                } else {
                    System.out.println("等待中。。。。。。");
                }
            }

        } catch (Exception e) {

        } finally {

        }
    }

    // 读取客户端的消息

    private void readData(SelectionKey selectionKey) {
        // 获取 socketChannel

        SocketChannel channel = null;
        try {
            channel = (SocketChannel) selectionKey.channel();
            ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
            int count = channel.read(byteBuffer);
            // 分情况处理
            if (count > 0) {
                // 获取到数据专程
                String msg = new String(byteBuffer.array(), 0, count);
                byteBuffer.clear();
                System.out.println(channel.getRemoteAddress() + "来自客户端" + msg);
                // 向其他的客户端转发消息
                sendInfoToOtherClients(msg, channel);
            }

        } catch (IOException e) {
            // 如果发生异常 提示说明离线了
            try {
                System.out.println(channel.getRemoteAddress() + "离线了。。。。");
                // 取消注册
                selectionKey.cancel();
                // 关闭通道
                channel.close();
            } catch (IOException e1) {
                //e1.printStackTrace();
            }
        } finally {

        }
    }


    // 转发消息给其他的客户端 去掉自己的客户端
    private void sendInfoToOtherClients(String msg, SocketChannel self) throws IOException {
        System.out.println("服务器转发消息。。。。。");
        // 进行遍历操作
        Set<SelectionKey> keys = selector.keys();
        for (SelectionKey key : keys) {
            // 取出来所有的
            Channel targetChannel = key.channel();
            // 排除自己
            if (targetChannel instanceof SocketChannel && targetChannel != self) {
                SocketChannel dest = (SocketChannel) targetChannel;
                ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
                // 发送数据
                dest.write(byteBuffer);
            }
        }
    }


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

二、客户端代码



public class GroupChatClient {

    // 定义相关属性

    private final String HOST = "127.0.0.1"; //服务器地址
    private final int port = 6667; // 服务器端口
    private Selector selector;
    private SocketChannel socketChannel;
    private String userName;

    // 完成初始化工作
    public GroupChatClient() {
        try {
            selector = Selector.open();
            // 连接服务器
            socketChannel = SocketChannel.open(new InetSocketAddress(HOST, port));
            // 设置非阻塞工作
            socketChannel.configureBlocking(false);
            // 注册我们的通道
            socketChannel.register(selector, SelectionKey.OP_READ);
            userName = socketChannel.getLocalAddress().toString();
            System.out.println("客户端专备好啦");
        } catch (IOException e) {

        }
    }

    public void sendInfo(String info) {
        String msg = userName + "说:" + info;
        try {
            ByteBuffer wrap = ByteBuffer.wrap(msg.getBytes());
            socketChannel.write(wrap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 读取信息
    public void readInfo() {
        try {
            int readChannel = selector.select(2000);
            if (readChannel > 0) {
                // 有可以用的通道
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey next = iterator.next();
                    if (next.isReadable()) {
                        SelectableChannel keyChannel = next.channel();
                        if (keyChannel instanceof SocketChannel) {
                            // 获取到我们的通道
                            SocketChannel channel = (SocketChannel) keyChannel;
                            ByteBuffer allocate = ByteBuffer.allocate(1024);
                            // 读取数据
                            int read = channel.read(allocate);
                            if (read > 0) {
                                // 输出我们的消息
                                System.out.println(new String(allocate.array(), 0, read));
                            }

                        }// end if
                    }
                    iterator.remove();
                }
            } else {
                System.out.println("没有可用的通道");
            }
        } catch (IOException e) {

        }
    }

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


        // 启动客户端的操作
        final GroupChatClient groupChatClient = new GroupChatClient();


        // 启动一个线程

        new Thread(() -> {
            while (true) {
                groupChatClient.readInfo();
                try {
                    Thread.currentThread().sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();


        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNext()) {
            // 输入信息
            String s = scanner.nextLine();
            groupChatClient.sendInfo(s);
        }


        System.in.read();
    }
}

三、运行的结果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。 

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯