Java NIO实现群聊功能

本文实例为大家分享了Java基于NIO实现群聊功能的具体代码,供大家参考。

 

一、群聊服务器

package com.dashu.netty.group_chat;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;


public class GroupChatServer {


  /**
   * 初始化选择器
   */
  private Selector selector;

  /**
   * 初始化服务器网络通道
   */
  private ServerSocketChannel serverSocketChannel;

  /**
   * 端口
   */
  private static final int PORT = 6666;


  /**
   * 构造方法
   */
  public GroupChatServer() {

      try {

          //获取选择器
          selector = Selector.open();

          //获取服务器网络通道
          serverSocketChannel = ServerSocketChannel.open();

          //网络地址
          InetSocketAddress inetSocketAddress = new InetSocketAddress(PORT);

          //服务器网络通道绑定网络地址
          serverSocketChannel.socket().bind(inetSocketAddress);

          //设置服务器网络通道非阻塞
          serverSocketChannel.configureBlocking(false);

          //将服务器网络通道注册到选择器上,绑定连接请求事件
          serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

      } catch (Exception e) {

          e.printStackTrace();

      }

  }


  /**
   * 监听客户端请求事件
   */
  public void listen() {


      try {

          //无限循环
          while (true) {

              //获取请求数
              int count = selector.select();

              //count大于0,则代表有请求进来
              if (count > 0) {


                  //获取请求集
                  Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator();

                  //遍历请求集
                  while (selectionKeyIterator.hasNext()) {

                      //得到请求
                      SelectionKey selectionKey = selectionKeyIterator.next();

                      //连接请求
                      if (selectionKey.isAcceptable()) {

                          //获取客户端网络通道
                          SocketChannel socketChannel = serverSocketChannel.accept();

                          //设置客户端网络通道非阻塞
                          socketChannel.configureBlocking(false);

                          //将客户端网络通道注册到选择器上
                          socketChannel.register(selector, SelectionKey.OP_READ);

                          System.out.println(socketChannel.getRemoteAddress() + "上线了");

                      }

                      //信息读取请求
                      if (selectionKey.isReadable()) {

                          //客户端信息读取
                          readData(selectionKey);

                      }

                      //移除请求
                      selectionKeyIterator.remove();

                  }


              } else {

                  System.out.println("等待...");

              }

          }
      } catch (Exception e) {
          e.printStackTrace();
      }

  }


  /**
   * 客户端信息读取
   *
   * @param selectionKey
   */
  private void readData(SelectionKey selectionKey) {

      //初始化客户端网络通道
      SocketChannel socketChannel = null;

      try {

          //获取客户端网络通道
          socketChannel = (SocketChannel) selectionKey.channel();

          //创建缓冲区
          ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

          //读取客户端网络通道中的数据到缓冲区
          int count = socketChannel.read(byteBuffer);

          //判断缓冲区中是否有数据
          if (count > 0) {

              //将缓冲区的数据转换位字符串
              String message = new String(byteBuffer.array());

              System.out.println(message.trim());

              //将信息群发到其他客户端
              sendInfoToOtClients(message, socketChannel);

          }

      } catch (Exception e) {

          e.printStackTrace();

      }


  }

  /**
   * 将信息群发到其他客户端
   *
   * @param message
   * @param socketChannel
   */
  private void sendInfoToOtClients(String message, SocketChannel socketChannel) {

      //获取所有注册到选择器的客户端,并遍历
      for (SelectionKey selectionKey : selector.keys()) {

          //获取通道
          Channel channel = selectionKey.channel();

          //判断通道是否属于SocketChannel,同时不等于发送信息的客户端
          if (channel instanceof SocketChannel && channel != socketChannel) {

              //通道转换
              SocketChannel sc = (SocketChannel) channel;

              //将信息写入缓冲区
              ByteBuffer byteBuffer = ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8));

              try {

                  //将缓冲区的数据写入通道
                  sc.write(byteBuffer);

              } catch (Exception e) {

                  e.printStackTrace();

              }

          }

      }

  }




  public static void main(String[] args) {

      GroupChatServer groupChatServer = new GroupChatServer();

      System.out.println("服务器启动,开始监听客户端请求...");
      groupChatServer.listen();

  }


}

 

二、客户端

package com.dashu.netty.group_chat;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Scanner;

public class GroupChatClient {


  /**
   * 网络连接地址
   */
  private final String HOST = "127.0.0.1";

  /**
   * 端口
   */
  private final int PORT = 6666;

  /**
   * 初始化选择器
   */
  private Selector selector;

  /**
   * 初始化网络通道
   */
  private SocketChannel socketChannel;


  /**
   * 用户名
   */
  private String username;


  public GroupChatClient() {
      try {

          //获取选择器
          selector = Selector.open();


          //获取服务器网络地址
          InetSocketAddress inetSocketAddress = new InetSocketAddress(HOST, PORT);

          //获取网络通道
          socketChannel = SocketChannel.open(inetSocketAddress);

          //设置网络通道非阻塞
          socketChannel.configureBlocking(false);


          //将网络通道注册到选择器
          socketChannel.register(selector, SelectionKey.OP_READ);


          //获取用户名
          System.out.println("请输入用户名:");

          Scanner scanner = new Scanner(System.in);

          username = scanner.nextLine();

          System.out.println(username + " 进入群聊...");

      } catch (Exception e) {

          e.printStackTrace();

      }
  }


  /**
   * 向服务器发送信息
   *
   * @param message
   */
  public void sendInfo(String message) {

      message = username + ":" + message;

      try {

          //向通道写入数据
          socketChannel.write(ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8)));

      } catch (Exception e) {

          e.printStackTrace();

      }

  }


  /**
   * 读取服务器发来的信息
   */
  public void readInfo() {
      try {

          //获取请求数
          int count = selector.select();

          if (count > 0) {

              //获取请求集
              Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator();

              //遍历请求集
              while (selectionKeyIterator.hasNext()) {

                  //获取请求
                  SelectionKey selectionKey = selectionKeyIterator.next();

                  //判断位读请求
                  if (selectionKey.isReadable()) {

                      //获取通道
                      SocketChannel sc = (SocketChannel) selectionKey.channel();

                      //创建缓冲区
                      ByteBuffer byteBuffer = ByteBuffer.allocate(1024);


                      //读取通道的数据到缓冲区
                      sc.read(byteBuffer);

                      //缓冲区数据转字符串
                      String message = new String(byteBuffer.array());

                      //输出
                      System.out.println(message.trim());

                  }

                  //移除已完成请求
                  selectionKeyIterator.remove();

              }

          }

      } catch (Exception e) {

          e.printStackTrace();

      }


  }


  public static void main(String[] args) {

      GroupChatClient groupChatClient = new GroupChatClient();

      /**
       * 开启一个线程,每3秒读取一次服务器发来的信息
       */
      new Thread() {
          @Override
          public void run() {
              while (true) {
                  groupChatClient.readInfo();
                  try {
                      Thread.sleep(3000);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }
      }.start();


      //信息输入
      Scanner scanner = new Scanner(System.in);

      System.out.println("请输入信息:");
      while (scanner.hasNextLine()) {

          String s = scanner.nextLine();

          //信息发送
          groupChatClient.sendInfo(s);

          System.out.println("请输入信息:");

      }
  }


}

 

三、效果图

1、服务器

2、客户端01

3、客户端02

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

目录结构1.在pom.xml文件中添加插件<profiles> <profile> <id>dev</id> <activ ...