千家信息网

java基于NIO如何实现群聊模式

发表于:2025-02-09 作者:千家信息网编辑
千家信息网最后更新 2025年02月09日,这篇文章将为大家详细讲解有关java基于NIO如何实现群聊模式,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体内容如下Clientpackage com.qst.
千家信息网最后更新 2025年02月09日java基于NIO如何实现群聊模式

这篇文章将为大家详细讲解有关java基于NIO如何实现群聊模式,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

具体内容如下

Client

package com.qst.chat;import java.io.IOException;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.util.Iterator;import java.util.Scanner;public class GroupChatClient { private final int PORT = 9999; private final String HOST = "localhost"; private SocketChannel channel; private static Selector selector; private String name;  public GroupChatClient() throws IOException {  selector = Selector.open();  // 连接服务器  channel = SocketChannel.open(new InetSocketAddress(HOST, PORT));  // 设置非阻塞  channel.configureBlocking(false);  // 将channel 注册到selector  channel.register(selector, SelectionKey.OP_READ);   name = channel.getLocalAddress().toString().substring(1);  System.out.println(name + "is ok ...."); } // 向服务器发送消息 public void sendTO(String msg) {    ByteBuffer buffer = ByteBuffer.wrap((name+":"+msg).getBytes());  try {   channel.write(buffer);  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } } // 读取从服务器端回复的消息 public static void getInfo() {    try {   if(selector.select() >0) {    Iterator iterator = selector.selectedKeys().iterator();        while(iterator.hasNext()) {     SelectionKey key = iterator.next();          if(key.isReadable()) {     // 得到通道     SocketChannel sc =  (SocketChannel) key.channel();          ByteBuffer buffer = ByteBuffer.allocate(1024);          int len;          // 把读到的缓冲区的数据转成字符串     while((len = sc.read(buffer)) > 0) {      System.out.println(new String(buffer.array()));     }          }           }    // 删除当前的selectionKey, 防止重复操作    iterator.remove();       }  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }   }  public static void main(String[] args) {  try {   GroupChatClient client = new GroupChatClient();         new Thread() {            public void run() {     while(true)     {      try {       Thread.sleep(3000);       GroupChatClient.getInfo();      } catch (InterruptedException e) {       // TODO Auto-generated catch block       e.printStackTrace();      }     }         };   }.start();         Scanner sc = new Scanner(System.in);//   while(true) {//    String name = sc.nextLine();//    client.sendTO(name);//   }   while(sc.hasNextLine()) {      String s = sc.nextLine();              client.sendTO(s);   }     } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } }}

Server端

package com.qst.chat;import java.io.IOException;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.net.Socket;import java.nio.ByteBuffer;import java.nio.channels.SelectableChannel;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.time.chrono.IsoChronology;import java.util.Iterator;import com.sun.accessibility.internal.resources.accessibility;import sun.print.resources.serviceui;public class GroupChatServer { private static ServerSocketChannel socketChannel; private static Socket socket; private static Selector selector; private static SocketChannel accept; public GroupChatServer() throws IOException {  socketChannel = ServerSocketChannel.open();  selector = Selector.open();  // 绑定端口  socketChannel.socket().bind(new InetSocketAddress(9999));  // 设置非阻塞模式  socketChannel.configureBlocking(false);  // 将该通道 注册到selector  socketChannel.register(selector, SelectionKey.OP_ACCEPT); } // 监听 public static void listen() {  System.out.println("监听线程: " + Thread.currentThread().getName());  try {   while (selector.select() > 0) {    Iterator iterator = selector.selectedKeys().iterator();    if (iterator.hasNext()) {     // 遍历得到selectionKey 集合     SelectionKey next = iterator.next();     if (next.isAcceptable()) {      next.channel();      // socketChannel = (ServerSocketChannel) next.channel();      SocketChannel accept = socketChannel.accept();      accept.configureBlocking(false);      accept.register(selector, SelectionKey.OP_READ);       System.out.println(accept.getRemoteAddress()+" 上线 了。。。");     }     if (next.isReadable()) {      readDate(next);     }     // 移除当前的next,防止重复处理     iterator.remove();     // System.out.println("未发现");    }   }  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } } // 读取客户端消息 public static void readDate(SelectionKey key) {  try {   accept = (SocketChannel) key.channel();   ByteBuffer buffer = ByteBuffer.allocate(1024);   int len = accept.read(buffer);   if (len > 0) {    buffer.flip();    String msg = new String(buffer.array());    System.out.println("user = " + msg);    // 向其它的客户端转发消息(去掉自己)    sendToAll(msg, accept);    buffer.clear();   }  } catch (IOException e) {   // TODO Auto-generated catch block   try {    String msg = accept.getRemoteAddress().toString();    // 取消注册    key.cancel();    // 关闭通道    accept.close();    System.out.println(msg + "离线了");   } catch (IOException e1) {    // TODO Auto-generated catch block    e1.printStackTrace();   }   // e.printStackTrace();  } finally {   // TODO: handle finally clause  } } public static void sendToAll(String msg, SocketChannel ssc) {  for (SelectionKey ss : selector.keys()) {   // 通过 key 取出对应的 SocketChannel   SelectableChannel channel = ss.channel();   // 排除自己   if (channel instanceof SocketChannel && channel != ssc) {    // 转型    SocketChannel sh = (SocketChannel) channel;    // 转存到buffer    ByteBuffer wrap = ByteBuffer.wrap(msg.getBytes());    try {     // 写入通道     sh.write(wrap);    } catch (IOException e) {     // TODO Auto-generated catch block     e.printStackTrace();    }   }  } } public static void main(String[] args) throws IOException {  GroupChatServer server = new GroupChatServer();  GroupChatServer.listen(); }}

key.isAcceptable()进行接入 操作的时候, 获取通道有两种方式

1、 通过selector获取 (Selector key) socketChannel = (ServerSocketChannel) key.channel();
建立连接 socketChannel .accept();

2、定义一个全局变量

在进行初始化的时候,存储(socketChannel = ServerSocketChannel.open();)
建立连接 socketChannel .accept();

key.isReadable() 当进行到读入操作的时候( ) SelectionKey key accept = (SocketChannel) key.channel();

演示

服务器启动,客户端启动


客户端发送消息

启动第二个客户端

两个客户端相互通信

离线信息显示

关于"java基于NIO如何实现群聊模式"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

0