基于NIO的简单群聊
直接贴代码
服务器端
package GroupChat;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
public class GroupServer {
private Selector selector;
private ServerSocketChannel listen;
private static final int PORT = 6667;
public GroupServer() {
try {
//得到选择器
selector = Selector.open();
//得到ServerSocketChannel
listen = ServerSocketChannel.open();
//绑定端口
listen.socket().bind(new InetSocketAddress(PORT));
//设置非阻塞
listen.configureBlocking(false);
//将ServerSocketChannel注册到Selector
listen.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
//监听
public void listen() {
try {
while (true) {
int count = selector.select(2000);
if (count > 0) {//有事件处理
//遍历得到selectionkey集合
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
//取出selectionkey
SelectionKey key = iterator.next();
//监听accept
if (key.isAcceptable()) {
SocketChannel socketChannel = listen.accept();
//注册到selector上
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
//提示
System.out.println(socketChannel.getRemoteAddress() + " 上线");
} else if (key.isReadable()) {//通道发生read事件,即通道是可读事件
readData(key);
}
//删除当前的key
iterator.remove();
}
} else {
System.out.println("等待");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//读取客户端消息
private void readData(SelectionKey key) throws IOException {
//定义一个SocketChannel
SocketChannel socketChannel = null;
try {
//取得关联的Channel
socketChannel = (SocketChannel) key.channel();
//创建缓冲
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int count = socketChannel.read(byteBuffer);
if (count > 0) {
//把缓冲区转换成字符串
String msg = new String(byteBuffer.array());
//输出该消息
System.out.println("from 客户端: " + msg);
//向其他的客户端转发消息(去掉自己)
forwardMsg(msg, socketChannel);
}
} catch (IOException e) {
System.out.println(socketChannel.getRemoteAddress() + " 离线了");
//取消注册
key.cancel();
//关闭通道
socketChannel.close();
e.printStackTrace();
}
}
//转发其他的消息
private void forwardMsg(String message, SocketChannel self) throws IOException {
System.out.println("服务器转发消息");
//遍历注册到selector上的SocketChannel并排除自己
for (SelectionKey key : selector.keys()) {
//通过对应的key取出对应的Channel
Channel targetChannel = key.channel();
//排除自己
if (targetChannel instanceof SocketChannel && targetChannel != self) {
//转型
SocketChannel dest = (SocketChannel) targetChannel;
//将msg存储到Buffer
ByteBuffer byteBuffer = ByteBuffer.wrap(message.getBytes());
//将Buffer的数据写入通道
dest.write(byteBuffer);
}
}
}
public static void main(String[] args) {
GroupServer groupServer = new GroupServer();
groupServer.listen();
}
}
客户端
package GroupChat;
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 GroupClient {
public static final String HOST = "127.0.0.1";
public static final int PORT = 6667;
private Selector selector;
private SocketChannel socketChannel;
private String username;
public GroupClient() {
try {
selector = Selector.open();
//连接服务器
socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT));
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
username = socketChannel.getLocalAddress().toString().substring(1);
System.out.println(username + " is OK");
} catch (IOException e) {
e.printStackTrace();
}
}
//向服务器发送消息
public void sendMsg(String info) {
info = username + "说:" + info;
try {
socketChannel.write(ByteBuffer.wrap(info.getBytes()));
} catch (IOException e) {
e.printStackTrace();
}
}
//读取服务器消息
public void readMsg() {
try {
int readChannels = selector.select();
if (readChannels > 0) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isReadable()) {
//得到相关通道
SocketChannel socketChannel = (SocketChannel) key.channel();
//得到一个Buffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//读取
socketChannel.read(byteBuffer);
String msg = new String(byteBuffer.array()).trim();
System.out.println(msg);
}
}
iterator.remove();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//启动客户端
GroupClient groupClient = new GroupClient();
//启动一个线程
new Thread(() -> {
while (true) {
groupClient.readMsg();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
//发送数据
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String s = scanner.nextLine();
groupClient.sendMsg(s);
}
}
}