溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

java基于NIO如何實(shí)現(xiàn)群聊模式

發(fā)布時(shí)間:2021-11-23 17:38:03 來(lái)源:億速云 閱讀:140 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)java基于NIO如何實(shí)現(xiàn)群聊模式,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

具體內(nèi)容如下

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();
  // 連接服務(wù)器
  channel = SocketChannel.open(new InetSocketAddress(HOST, PORT));
  // 設(shè)置非阻塞
  channel.configureBlocking(false);
  // 將channel 注冊(cè)到selector
  channel.register(selector, SelectionKey.OP_READ);
   name = channel.getLocalAddress().toString().substring(1);

  System.out.println(name + "is ok ....");

 }
 // 向服務(wù)器發(fā)送消息
 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();
  }

 }
 // 讀取從服務(wù)器端回復(fù)的消息
 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;
     
     // 把讀到的緩沖區(qū)的數(shù)據(jù)轉(zhuǎn)成字符串
     while((len = sc.read(buffer)) > 0) {
      System.out.println(new String(buffer.array()));
     }
     
     }
  
     
    }
    // 刪除當(dāng)前的selectionKey, 防止重復(fù)操作
    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));
  // 設(shè)置非阻塞模式
  socketChannel.configureBlocking(false);

  // 將該通道 注冊(cè)到selector
  socketChannel.register(selector, SelectionKey.OP_ACCEPT);

 }

 // 監(jiān)聽(tīng)
 public static void listen() {
  System.out.println("監(jiān)聽(tīng)線程: " + 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);

     }

     // 移除當(dāng)前的next,防止重復(fù)處理
     iterator.remove();
     // System.out.println("未發(fā)現(xiàn)");

    }

   }
  } 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);

    // 向其它的客戶端轉(zhuǎn)發(fā)消息(去掉自己)
    sendToAll(msg, accept);
    buffer.clear();
   }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   try {
    String msg = accept.getRemoteAddress().toString();
    // 取消注冊(cè)
    key.cancel();
    // 關(guān)閉通道
    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()) {
   // 通過(guò) key 取出對(duì)應(yīng)的 SocketChannel
   SelectableChannel channel = ss.channel();

   // 排除自己
   if (channel instanceof SocketChannel && channel != ssc) {
    // 轉(zhuǎn)型
    SocketChannel sh = (SocketChannel) channel;
    // 轉(zhuǎn)存到buffer
    ByteBuffer wrap = ByteBuffer.wrap(msg.getBytes());
    try {
     // 寫(xiě)入通道
     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()進(jìn)行接入 操作的時(shí)候, 獲取通道有兩種方式

1、 通過(guò)selector獲取 (Selector key) socketChannel = (ServerSocketChannel) key.channel();
建立連接 socketChannel .accept();

2、定義一個(gè)全局變量

在進(jìn)行初始化的時(shí)候,存儲(chǔ)(socketChannel = ServerSocketChannel.open();)
建立連接 socketChannel .accept();

key.isReadable() 當(dāng)進(jìn)行到讀入操作的時(shí)候( ) SelectionKey key accept = (SocketChannel) key.channel();

演示

服務(wù)器啟動(dòng),客戶端啟動(dòng)

java基于NIO如何實(shí)現(xiàn)群聊模式

java基于NIO如何實(shí)現(xiàn)群聊模式

客戶端發(fā)送消息

java基于NIO如何實(shí)現(xiàn)群聊模式

啟動(dòng)第二個(gè)客戶端

java基于NIO如何實(shí)現(xiàn)群聊模式

java基于NIO如何實(shí)現(xiàn)群聊模式

兩個(gè)客戶端相互通信

java基于NIO如何實(shí)現(xiàn)群聊模式

java基于NIO如何實(shí)現(xiàn)群聊模式

java基于NIO如何實(shí)現(xiàn)群聊模式

離線信息顯示

java基于NIO如何實(shí)現(xiàn)群聊模式

關(guān)于“java基于NIO如何實(shí)現(xiàn)群聊模式”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI