server
java
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 serverSocketChannel;
private static final int PORT = 6667;
public GroupServer() {
try {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 监听
*/
public void listen() {
System.out.println("开始监听");
try {
// 需要轮询获取事件
while (true) {
// 阻塞两秒 获取事件
int count = selector.select(2000);
if (count > 0) {
// 有事件进来了 有可能并发来的 所以需要循环 获取事件 并处理
Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
// 这块是先关心accept事件 获取之后 立马就关心read事件
if (key.isAcceptable()) {
// 获取到客户端的连接
SocketChannel sc = serverSocketChannel.accept();
// 设置非阻塞 注册到selector 关注read事件 并给一个buffer
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
System.out.println("用户 " + sc.getRemoteAddress() + " 上线了");
}
// 立马关注读事件
if (key.isReadable()) {
// selectionKey 和channel是绑定的 1对1 key中也就是事件 绑定channel 获取数据
readData(key);
}
}
keyIterator.remove();
}else {
// System.out.println("等待中。。。");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
/**
* 发送消息给其他客户端
* @param msg
* @param self
*/
public void sendInfoToOtherClients(String msg, SocketChannel self) {
try {
// 遍历所有注册到selector上的socketChannel 并排除自己
for (SelectionKey key : selector.keys()) {
Channel channel = key.channel();
if (channel instanceof SocketChannel && channel != self) {
ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
((SocketChannel) channel).write(buffer);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
/**
* 读取客户端消息
* @param key
*/
private void readData(SelectionKey key) {
SocketChannel socketChannel = null;
try {
socketChannel = (SocketChannel) key.channel();
// 创建buffer 读取数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
int count = socketChannel.read(buffer);
//根据count的值做处理
if (count > 0) {
//读取到数据
String msg = new String(buffer.array());
System.out.println("from client 消息:" + msg.trim());
//向其他客户端转发消息
sendInfoToOtherClients(msg, socketChannel);
}
} catch (Exception e) {
try {
System.out.println(socketChannel.getRemoteAddress() + " 离线了");
key.cancel();
socketChannel.close();
} catch (IOException e2) {
e2.printStackTrace();
}
} finally {
}
}
public static void main(String[] args) {
try {
GroupServer groupServer = new GroupServer();
groupServer.listen();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
client
java
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 {
private static final String HOST = "127.0.0.1";
private static final int PORT = 6667;
private Selector selector;
private String userName;
private SocketChannel socketChannel;
public GroupClient() throws Exception {
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 + " client is ok");
}
public void sendInfo(String info) {
info = userName + " 说:" + info;
try {
socketChannel.write(ByteBuffer.wrap(info.getBytes()));
} catch (Exception e) {
e.printStackTrace();
}
}
public void readInfo() {
try {
int readChannels = selector.select(2000);
if (readChannels > 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);
sc.read(buffer);
String msg = new String(buffer.array());
System.out.println(msg.trim());
}
iterator.remove();
}
}else {
// System.out.println("没有可用的通道");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
public static void main(String[] args) throws Exception {
GroupClient client = new GroupClient();
// 开启一个线程 读取从服务器端回复的消息 (客户端)
new Thread(()->{
while (true) {
client.readInfo();
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// 主线程 发送数据给服务器端
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String s = scanner.nextLine();
client.sendInfo(s);
}
}
}