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<SelectionKey> 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<SelectionKey> 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<SelectionKey> 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");
    }

}

NIO 聊天室到此结束

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

(0)

相关推荐

  • java基于netty NIO的简单聊天室的实现

    一.为何要使用netty开发 由于之前已经用Java中的socket写过一版简单的聊天室,这里就不再对聊天室的具体架构进行细致的介绍了,主要关注于使用netty框架重构后带来的改变.对聊天室不了解的同学可以先看下我的博客(<JAVA简单聊天室的实现>) 本篇博客所使用的netty版本为4.1.36,完整工程已上传到Github(https://github.com/Alexlingl/Chatroom),其中lib文件夹下有相应的netty jar包和source包,自行导入即可. 1.为何要

  • Java基于NIO实现聊天室功能

    本文实例为大家分享了Java基于NIO实现聊天室功能的具体代码,供大家参考,具体内容如下 Sever端 package com.qst.one; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.Channel; import java.nio.channels.SelectableChannel; impor

  • Java NIO实现聊天室功能

    本文实例为大家分享了Java NIO实现聊天室功能的具体代码,供大家参考,具体内容如下 代码里面已经包含了必要的注释,这里不详述了.实现了基本的聊天室功能. 常量类: public class Constant { public static final int serverPort = 44444; } 服务端: package server; import java.io.IOException; import java.net.InetSocketAddress; import java.

  • Java实现NIO聊天室的示例代码(群聊+私聊)

    功能介绍 功能:群聊+私发+上线提醒+下线提醒+查询在线用户 文件 Utils 需要用maven导入下面两个包 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <dependency> <group

  • Java NIO实战之聊天室功能详解

    本文实例讲述了Java NIO实战之聊天室功能.分享给大家供大家参考,具体如下: 在工作之余花了两个星期看完了<Java NIO>,总体来说这本书把NIO写的很详细,没有过多的废话,讲的都是重点,只是翻译的中文版看的确实吃力,英文水平太低也没办法,总算也坚持看完了.<Java NIO>这本书的重点在于第四章讲解的"选择器",要理解透还是要反复琢磨推敲:愚钝的我花了大概3天的时间才将NIO的选择器机制理解透并能较熟练的运用,于是便写了这个聊天室程序. 下面直接上代

  • Java NIO实现多人聊天室

    本文实例为大家分享了Java NIO实现多人聊天室的具体代码,供大家参考,具体内容如下 1. 服务器端代码 ChatServer类: package nio.test.server; import java.io.Closeable; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.n

  • Java NIO Selector用法详解【含多人聊天室实例】

    本文实例讲述了Java NIO Selector用法.分享给大家供大家参考,具体如下: 一.Java NIO 的核心组件 Java NIO的核心组件包括:Channel(通道),Buffer(缓冲区),Selector(选择器),其中Channel和Buffer比较好理解 简单来说 NIO是面向通道和缓冲区的,意思就是:数据总是从通道中读到buffer缓冲区内,或者从buffer写入到通道中. 关于Channel 和 Buffer的详细讲解请看:Java NIO 教程 二.Java NIO Se

  • JAVA NIO实现简单聊天室功能

    本文实例为大家分享了JAVA NIO实现简单聊天室功能的具体代码,供大家参考,具体内容如下 服务端 初始化一个ServerSocketChannel,绑定端口,然后使用Selector监听accept事件. 当有accept发生时,表示有客户端连接进来了,获取客户端的SocketChannel,然后注册其read事件:用来接收客户端发送的消息. package chatroom; import java.io.IOException; import java.net.InetSocketAddr

  • Java NIO实战之多人聊天室

    本文实例为大家分享了Java NIO实战之多人聊天室的具体代码,供大家参考,具体内容如下 NIO服务端 public class NioServer { /** * 启动 */ public void start() throws IOException { /** * 1. 创建Selector */ Selector selector = Selector.open(); /** * 2. 通过ServerSocketChannel创建channel通道 */ ServerSocketCha

  • Java Socket+多线程实现多人聊天室功能

    本文实例为大家分享了Java Socket+多线程实现多人聊天室的具体代码,供大家参考,具体内容如下 思路简介 分为客户端和服务器两个类,所有的客户端将聊的内容发送给服务器,服务器接受后,将每一条内容发送给每一个客户端,客户端再显示在终端上. 客户端设计 客户端包含2个线程,1个用来接受服务器的信息,再显示,1个用来接收键盘的输入,发送给服务器. import java.io.IOException; import java.io.InputStream; import java.io.Outp

  • java控制台输出版多人聊天室

    本文实例为大家分享了java控制台输出版多人聊天室的具体代码,供大家参考,具体内容如下 多人聊天室就要用到网络以及多线程以及输入输出流的知识 多人聊天室就是多个人同时聊天,一个发一条信息所有人都是可以接收得到. 接下来我们捋清楚一下思路 在这里面服务器充当了一个转发的作用,服务器要做的事情是,得到客户写进缓冲流里面的信息,再把得到的信息再写进其他客户端的缓冲流里面,得到其他用户的缓冲流我们可以通过集合把用户的全部Socket对象写进集合里面,客户端把客户想要发送的信息写进缓冲流里,等待客户端发来

  • Java基于Socket实现多人聊天室

    本文实例为大家分享了Java基于Socket实现简易版多人聊天室的具体代码,供大家参考,具体内容如下 一. 聊天室需求 1.一个服务端,多个客户端:2.实现客户端和服务端的交互:3.客户端发送信息,服务端收到信息,再转发给其他客户端:4.上下线时显示哪个客户端上下线并且显示在线客户端数量: 二.代码分析 1. 建立连接 客户端类,创建发送端Socket对象,用自己的IP地址和端口号,与服务端建立连接. class Client: //用于与服务端通信的Socket private Socket

  • Java通过Socket实现简单多人聊天室

    本文实例为大家分享了Java通过Socket实现多人聊天室的具体代码,供大家参考,具体内容如下 Socket可以实现网络上两个程序通过双向通道进行数据的交换,此外它是Java中网络TCP/IP协议的封装,例如可以进行网络通信等等,下面我们就来简单写一下多人聊天室. 首先来分析一下要实现的流程 首先建立一个服务器端,构建ServerSocket并绑定端口 创建socket客户端,连接到指定ip以及其端口 然后使用accept阻塞接收socket发出的连接请求 获取连接后的socket客户端的输入流

  • Java基于中介者模式实现多人聊天室功能示例

    本文实例讲述了Java基于中介者模式实现多人聊天室功能.分享给大家供大家参考,具体如下: 一 模式定义 中介者模式,用一个中介对象来封装一系列对象之间的交互,使各个对象中不需要显示地引用其他对象实例,从而降低各个对象之间的耦合度,并且可以独立地改变对象间的交互关系. 二 模式举例 1 模式分析 我们借用多人聊天室来说明这一模式 2 中介模式静态类图 3 代码示例 3.1中介者接口--IMediator package com.demo.mediator; import com.demo.coll

  • Go语言多人聊天室项目实战

    本文为大家分享了Go语言多人聊天室项目实战,供大家参考,具体内容如下 功能需求 实现单撩 实现群撩 实现用户上线的全网通知 实现用户昵称 实现聊天日志的存储和查看 服务端实现 type Client struct { conn net.Conn name string addr string } var ( //客户端信息,用昵称为键 //clientsMap = make(map[string]net.Conn) clientsMap = make(map[string]Client) ) f

随机推荐