这篇文章将为大家详细讲解有关爪哇岛基于尼奥如何实现群聊模式,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
具体内容如下
Client
打包。qst。聊天;
导入Java。io。ioexception
导入Java。净。inetsocketaddress
导入Java。尼奥。Bytebuffer
导入Java。尼奥。频道。选择键;
导入Java。尼奥。频道。选择器;
导入Java。尼奥。频道。Socketchannel
导入Java。乌提尔。迭代器;
导入Java。乌提尔。扫描仪;
publicclassGroupChatClient{
privatefinalintPORT=9999
privatefilestringghost=' localhost ';
privateSocketChannelchannel
私人选民选择器;
私有字符串名称
publicGroupChatClient(){ throwSioException }
选择器=选择器。open();
//连接服务器
channel=Socketchannel。open(Newinetsocketaddress(HOST,PORT));
//设置非阻塞
频道。configure blocking(false);
//将引导注册到选择器
channel.register(选择器,选择键. OP _ READ);
name=channel.getLocalAddress().toString().子串(1);
System.out.println(名称isok’);
}
//向服务器发送消息
publicationsendto(Stringmsg){ 0
bytebuffer缓冲区=bytebuffer。包装((名称' : ' msg).getBytes());
尝试{
channel.write(缓冲区);
} catch(IOexceptione){ 0
//到自动生成的捕捉块
e。print stack trace();
}
}
//读取从服务器端回复的消息
publicationstatvogetinfo(){ 0
尝试{
if(选择器。选择)(0){ 0
迭代器选择键迭代器=选择器。迭代器();
while(迭代器。HasNeXt()){ 0
选择关键关键点b
sp;= 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如何实现群聊模式”这篇文章就分享到这里了,希望
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/113337.html