Java NIO实现聊天系统

作者:菜鸟程序猿进阶之路 时间:2023-08-08 08:35:36 

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

一、服务端


/**
* 群聊的服端
*
* @author :breakpoint/赵立刚
* @date : 2020/08/13
*/
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();
   }
}

二、客户端代码


/**
* @author :breakpoint/赵立刚
* @date : 2020/08/13
*/
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();
   }
}

三、运行的结果

Java NIO实现聊天系统

Java NIO实现聊天系统

来源:https://blog.csdn.net/zhaoligang1234/article/details/107988923

标签:Java,NIO,聊天系统
0
投稿

猜你喜欢

  • 解决IDEA和CMD中java命令提示错误: 找不到或无法加载主类的问题

    2023-09-19 02:31:16
  • C#使用二分查找法判断指定字符的方法

    2022-08-02 06:46:30
  • C#解决文件被占用资源,无法删除或修改的方法

    2023-10-25 14:39:57
  • C#实现IP摄像头的方法

    2023-12-09 03:42:51
  • 使用SpringBoot-JPA进行自定义保存及批量保存功能

    2022-05-26 22:42:43
  • java实现最短路径算法之Dijkstra算法

    2021-12-28 12:26:06
  • Java优化if-else代码的实战记录

    2023-05-16 22:55:18
  • 一个简单的Python名片管理系统

    2022-09-20 09:26:15
  • java多线程加锁以及Condition类的使用实例解析

    2023-08-07 07:25:30
  • Android带圆形数字进度的自定义进度条示例

    2021-10-04 20:20:01
  • Android仿微信朋友圈实现滚动条下拉反弹效果

    2023-02-21 15:48:58
  • 两种JAVA实现短网址服务算法

    2023-05-08 12:17:30
  • 详解MyBatis-Plus Wrapper条件构造器查询大全

    2023-09-05 08:55:52
  • java文件操作工具类分享(file文件工具类)

    2023-11-24 22:32:47
  • Android高手进阶教程(二十六)之---Android超仿Path菜单的功能实现!

    2022-05-13 01:16:58
  • 基于java实现人机猜拳游戏

    2021-06-09 08:50:32
  • 详解C# 泛型中的数据类型判定与转换

    2023-05-03 08:08:36
  • java中归并排序和Master公式详解

    2022-03-30 08:53:19
  • SpringBoot Actuator未授权访问漏洞修复详解

    2022-03-30 16:43:28
  • 如何用C#创建用户自定义异常浅析

    2023-06-10 20:06:16
  • asp之家 软件编程 m.aspxhome.com