千家信息网

怎么使用Java NIO实现多人聊天室

发表于:2024-11-22 作者:千家信息网编辑
千家信息网最后更新 2024年11月22日,本篇内容主要讲解"怎么使用Java NIO实现多人聊天室",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么使用Java NIO实现多人聊天室"吧!NIO服
千家信息网最后更新 2024年11月22日怎么使用Java NIO实现多人聊天室

本篇内容主要讲解"怎么使用Java NIO实现多人聊天室",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么使用Java NIO实现多人聊天室"吧!

NIO服务端

public class NioServer {    /**     * 启动     */    public void start() throws IOException {        /**         * 1. 创建Selector         */        Selector selector = Selector.open();        /**         * 2. 通过ServerSocketChannel创建channel通道         */        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();        /**         * 3. 为channel通道绑定监听端口         */        serverSocketChannel.bind(new InetSocketAddress(8000));        /**         * 4. **设置channel为非阻塞模式**         */        serverSocketChannel.configureBlocking(false);        /**         * 5. 将channel注册到selector上,监听连接事件         */        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);        System.out.println("服务器启动成功!");        /**         * 6. 循环等待新接入的连接         */        for (;;) { // while(true) c for;;            /**             * TODO 获取可用channel数量             */            int readyChannels = selector.select();            /**             * TODO 为什么要这样!!?             */            if (readyChannels == 0) continue;            /**             * 获取可用channel的集合             */            Set selectionKeys = selector.selectedKeys();            Iterator iterator = selectionKeys.iterator();            while (iterator.hasNext()) {                /**                 * selectionKey实例                 */                SelectionKey selectionKey = (SelectionKey) iterator.next();                /**                 * **移除Set中的当前selectionKey**                 */                iterator.remove();                /**                 * 7. 根据就绪状态,调用对应方法处理业务逻辑                 */                /**                 * 如果是 接入事件                 */                if (selectionKey.isAcceptable()) {                    acceptHandler(serverSocketChannel, selector);                }                /**                 * 如果是 可读事件                 */                if (selectionKey.isReadable()) {                    readHandler(selectionKey, selector);                }            }        }    }    /**     * 接入事件处理器     */    private void acceptHandler(ServerSocketChannel serverSocketChannel,                               Selector selector)            throws IOException {        /**         * 如果要是接入事件,创建socketChannel         */        SocketChannel socketChannel = serverSocketChannel.accept();        /**         * 将socketChannel设置为非阻塞工作模式         */        socketChannel.configureBlocking(false);        /**         * 将channel注册到selector上,监听 可读事件         */        socketChannel.register(selector, SelectionKey.OP_READ);        /**         * 回复客户端提示信息         */        socketChannel.write(Charset.forName("UTF-8")                .encode("你与聊天室里其他人都不是朋友关系,请注意隐私安全"));    }    /**     * 可读事件处理器     */    private void readHandler(SelectionKey selectionKey, Selector selector)            throws IOException {        /**         * 要从 selectionKey 中获取到已经就绪的channel         */        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();        /**         * 创建buffer         */        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);        /**         * 循环读取客户端请求信息         */        String request = "";        while (socketChannel.read(byteBuffer) > 0) {            /**             * 切换buffer为读模式             */            byteBuffer.flip();            /**             * 读取buffer中的内容             */            request += Charset.forName("UTF-8").decode(byteBuffer);        }        /**         * 将channel再次注册到selector上,监听他的可读事件         */        socketChannel.register(selector, SelectionKey.OP_READ);        /**         * 将客户端发送的请求信息 广播给其他客户端         */        if (request.length() > 0) {            // 广播给其他客户端            broadCast(selector, socketChannel, request);        }    }    /**     * 广播给其他客户端     */    private void broadCast(Selector selector,                           SocketChannel sourceChannel, String request) {        /**         * 获取到所有已接入的客户端channel         */        Set selectionKeySet = selector.keys();        /**         * 循环向所有channel广播信息         */        selectionKeySet.forEach(selectionKey -> {            Channel targetChannel = selectionKey.channel();            // 剔除发消息的客户端            if (targetChannel instanceof SocketChannel                    && targetChannel != sourceChannel) {                try {                    // 将信息发送到targetChannel客户端                    ((SocketChannel) targetChannel).write(                            Charset.forName("UTF-8").encode(request));                } catch (IOException e) {                    e.printStackTrace();                }            }        });    }    /**     * 主方法     * @param args     */    public static void main(String[] args) throws IOException {        new NioServer().start();    }}

NIO客户端

public class NioClient {    /**     * 启动     */    public void start(String nickname) throws IOException {        /**         * 连接服务器端         */        SocketChannel socketChannel = SocketChannel.open(                new InetSocketAddress("127.0.0.1", 8000));        /**         * 接收服务器端响应         */        // 新开线程,专门负责来接收服务器端的响应数据        // selector , socketChannel , 注册        Selector selector = Selector.open();        socketChannel.configureBlocking(false);        socketChannel.register(selector, SelectionKey.OP_READ);        new Thread(new NioClientHandler(selector)).start();        /**         * 向服务器端发送数据         */        Scanner scanner = new Scanner(System.in);        while (scanner.hasNextLine()) {            String request = scanner.nextLine();            if (request != null && request.length() > 0) {                socketChannel.write(                        Charset.forName("UTF-8")                                .encode(nickname + " : " + request));            }        }    }    public static void main(String[] args) throws IOException {//        new NioClient().start();    }}

客户端线程,处理服务器端响应的的消息

public class NioClientHandler implements Runnable {    private Selector selector;    public NioClientHandler(Selector selector) {        this.selector = selector;    }    @Override    public void run() {        try {            for (;;) {                int readyChannels = selector.select();                if (readyChannels == 0) continue;                /**                 * 获取可用channel的集合                 */                Set selectionKeys = selector.selectedKeys();                Iterator iterator = selectionKeys.iterator();                while (iterator.hasNext()) {                    /**                     * selectionKey实例                     */                    SelectionKey selectionKey = (SelectionKey) iterator.next();                    /**                     * **移除Set中的当前selectionKey**                     */                    iterator.remove();                    /**                     * 7. 根据就绪状态,调用对应方法处理业务逻辑                     */                    /**                     * 如果是 可读事件                     */                    if (selectionKey.isReadable()) {                        readHandler(selectionKey, selector);                    }                }            }        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * 可读事件处理器     */    private void readHandler(SelectionKey selectionKey, Selector selector)            throws IOException {        /**         * 要从 selectionKey 中获取到已经就绪的channel         */        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();        /**         * 创建buffer         */        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);        /**         * 循环读取服务器端响应信息         */        String response = "";        while (socketChannel.read(byteBuffer) > 0) {            /**             * 切换buffer为读模式             */            byteBuffer.flip();            /**             * 读取buffer中的内容             */            response += Charset.forName("UTF-8").decode(byteBuffer);        }        /**         * 将channel再次注册到selector上,监听他的可读事件         */        socketChannel.register(selector, SelectionKey.OP_READ);        /**         * 将服务器端响应信息打印到本地         */        if (response.length() > 0) {            System.out.println(response);        }    }}

我们定义三个客户端,模拟三个用户在聊天室发送消息

public class AClient {    public static void main(String[] args)            throws IOException {        new NioClient().start("AClient");    }}public class BClient {    public static void main(String[] args)            throws IOException {        new NioClient().start("BClient");    }}public class CClient {    public static void main(String[] args)            throws IOException {        new NioClient().start("CClient");    }}

到此,相信大家对"怎么使用Java NIO实现多人聊天室"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0