欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java基于NIO实现群聊模式

程序员文章站 2022-03-15 20:54:14
本文实例为大家分享了java基于nio实现群聊模式的具体代码,供大家参考,具体内容如下clientpackage com.qst.chat;import java.io.ioexception;imp...

本文实例为大家分享了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<selectionkey> 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<selectionkey> 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实现群聊模式

java基于NIO实现群聊模式

客户端发送消息

java基于NIO实现群聊模式

启动第二个客户端

java基于NIO实现群聊模式

java基于NIO实现群聊模式

两个客户端相互通信

java基于NIO实现群聊模式

java基于NIO实现群聊模式

java基于NIO实现群聊模式

离线信息显示

java基于NIO实现群聊模式

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

相关标签: java 群聊