服务端:
package com.wq.nio;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class NioServer {
private static Map<String,SocketChannel> clientMap = new HashMap<String,SocketChannel>();
public static void main(String[] args) throws Exception{
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//打开服务器套接字通道,底层通过SelectorProvider
serverSocketChannel.configureBlocking(false);//设置通道的阻塞模式false是非阻塞
ServerSocket serverSocket = serverSocketChannel.socket();//检索与此通道关联的服务器套接字
serverSocket.bind(new InetSocketAddress(8899));
Selector selector = Selector.open();//打开选择器
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//将通道注册在选择器上,指定感兴趣的SelectionKey
while (true){
int num = selector.select();//select是阻塞的,一直到至少有一个channel is selected
Set<SelectionKey> selectionKeys = selector.selectedKeys();//获取SelectionKey的set集合
selectionKeys.forEach(selectionKey -> {
SocketChannel client;
try {
if(selectionKey.isAcceptable()){
ServerSocketChannel serverSocketChannel1 = (ServerSocketChannel) selectionKey.channel();
client = serverSocketChannel1.accept();
client.configureBlocking(false);
client.register(selector,SelectionKey.OP_READ);
clientMap.put(UUID.randomUUID().toString(),client);
}else if (selectionKey.isReadable()){
client = (SocketChannel) selectionKey.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int count = client.read(readBuffer);
if(count>0){
readBuffer.flip();
Charset charset = Charset.forName("utf-8");
String receiveMessage = String.valueOf(charset.decode(readBuffer).array());
System.out.println(client+":"+receiveMessage);
String sendKey = null;
for (Map.Entry<String,SocketChannel> entry : clientMap.entrySet()){
if(client == entry.getValue()){
sendKey = entry.getKey();
break;
}
}
for (Map.Entry<String,SocketChannel> entry : clientMap.entrySet()){
SocketChannel socketChannel = entry.getValue();
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
writeBuffer.put((sendKey+";"+receiveMessage).getBytes());
writeBuffer.flip();
socketChannel.write(writeBuffer);
}
}
}
}catch (Exception e){
e.printStackTrace();
}
});
selectionKeys.clear();
}
}
}
客户端
package com.wq.nio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NioClient {
public static void main(String[] args) {
try{
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
Selector selector = Selector.open();
socketChannel.register(selector, SelectionKey.OP_CONNECT);
socketChannel.connect(new InetSocketAddress("127.0.0.1",8899));
while (true){
selector.select();
Set<SelectionKey> keySet= selector.selectedKeys();
keySet.forEach(selectionKey->{
if (selectionKey.isConnectable()){
SocketChannel client = (SocketChannel) selectionKey.channel();
if(client.isConnectionPending()){ //指示此通道上是否正在进行连接操作
try {
client.finishConnect();//完成连接套接字通道的过程
ByteBuffer writeByffer = ByteBuffer.allocate(1024);
writeByffer.put((LocalDateTime.now()+"连接成功").getBytes());
writeByffer.flip();
client.write(writeByffer);
ExecutorService executorService = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
executorService.submit(()->{
while (true){
try{
writeByffer.clear();
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(in);
String SendMessage = br.readLine();
writeByffer.put(SendMessage.getBytes());
writeByffer.flip();
client.write(writeByffer);
}catch (Exception e){
e.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
try {
client.register(selector,SelectionKey.OP_READ);
} catch (ClosedChannelException e) {
e.printStackTrace();
}
}else if(selectionKey.isReadable()){
SocketChannel client = (SocketChannel) selectionKey.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
try {
int count = client.read(readBuffer);
if(count>0){
String receiveMessage = new String(readBuffer.array(),0,count);
System.out.println("receiveMessage:"+receiveMessage);
}
} catch (IOException e) {
e.printStackTrace();
}
}
keySet.clear();
});
}
}catch(Exception e){
e.printStackTrace();
}
}
}
运行结果:
多客户端输入,服务端获取后再转发给所有已经连接的客户端