软件编程
位置:首页>> 软件编程>> java编程>> Java NIO实战之多人聊天室

Java NIO实战之多人聊天室

作者:红字V  发布时间:2022-02-28 15:05:00 

标签: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 聊天室到此结束

来源:https://blog.csdn.net/sinat_36899414/article/details/106169245

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com