服务端代码
public class ChatServer {
private static Map<String, SocketChannel> clientsMap = new HashMap<>();
public static void main(String[] args) throws IOException {
int[] ports = new int[]{7777,8888,9999};
Selector selector = Selector.open();
for(int port : ports) {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
ServerSocket serverSocket = serverSocketChannel.socket();
serverSocket.bind(new InetSocketAddress(port));
System.out.println("服务端启动成功,端口:" + port);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}
while(true){
selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while(keyIterator.hasNext()){
SelectionKey selectedKey = keyIterator.next();
String receive = null;
SocketChannel clientChannel;
try {
if(selectedKey.isAcceptable()){
ServerSocketChannel server = (ServerSocketChannel) selectedKey.channel();
clientChannel = server.accept();
clientChannel.configureBlocking(false);
clientChannel.register(selector, SelectionKey.OP_READ);
String key = "游客" + (int)(Math.random()*9000 + 1000);
clientsMap.put(key, clientChannel);
}
else if(selectedKey.isReadable()){
clientChannel = (SocketChannel) selectedKey.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int result = -1;
try {
result = clientChannel.read(readBuffer);
} catch (IOException e) {
String clientKey = getClientKey(clientChannel);
System.out.println("客户端" + clientKey + "退出了聊天室");
clientsMap.remove(clientKey);
clientChannel.close();
selectedKey.cancel();
continue;
}
if(result > 0){
readBuffer.flip();
Charset charset = Charset.forName("utf-8");
receive = String.valueOf(charset.decode(readBuffer).array());
System.out.println(clientChannel + ":" + receive);
if("connecting".equals(receive)){
receive = "新客户端加入聊天!";
}
selectedKey.attach(receive);
selectedKey.interestOps(SelectionKey.OP_WRITE);
}
}
else if(selectedKey.isWritable()){
clientChannel = (SocketChannel) selectedKey.channel();
String sendKey = getClientKey(clientChannel);
for(Map.Entry<String, SocketChannel> entry : clientsMap.entrySet()){
SocketChannel eachClient = entry.getValue();
ByteBuffer broadcastMsg = ByteBuffer.allocate(1024);
broadcastMsg.put((sendKey + ":" + selectedKey.attachment()).getBytes());
broadcastMsg.flip();
eachClient.write(broadcastMsg);
}
selectedKey.interestOps(SelectionKey.OP_READ);
}
} catch (IOException e) {
e.printStackTrace();
}
}
selectionKeys.clear();
}
}
public static String getClientKey(SocketChannel clientChannel){
String sendKey = null;
for(Map.Entry<String, SocketChannel> entry : clientsMap.entrySet()){
if(clientChannel == entry.getValue()){
sendKey = entry.getKey();
break;
}
}
return sendKey;
}
}
客户端代码
public class ChatClient {
public static void main(String[] args) {
try {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
Selector selector = Selector.open();
socketChannel.register(selector, SelectionKey.OP_CONNECT);
int[] ports = {7777, 8888, 9999};
int port = ports[(int)(Math.random() * 3)];
socketChannel.connect(new InetSocketAddress("127.0.0.1", port));
while(true){
selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while(keyIterator.hasNext()){
SelectionKey selectedKey = keyIterator.next();
if(selectedKey.isConnectable()){
ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
SocketChannel client = (SocketChannel) selectedKey.channel();
if(client.isConnectionPending()){
boolean isConnected = client.finishConnect();
if(isConnected){
System.out.println("连接成功!访问的端口是:" + port);
sendBuffer.put("connecting".getBytes());
sendBuffer.flip();
client.write(sendBuffer);
}
new Thread(()->{
while(true){
try {
sendBuffer.clear();
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader bReader = new BufferedReader(reader);
String message = bReader.readLine();
sendBuffer.put(message.getBytes());
sendBuffer.flip();
client.write(sendBuffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
client.register(selector, SelectionKey.OP_READ);
}
}
else if(selectedKey.isReadable()){
SocketChannel client = (SocketChannel) selectedKey.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int len = client.read(readBuffer);
if(len > 0){
String receive = new String(readBuffer.array(), 0, len);
System.out.println(receive);
}
}
}
selectionKeys.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
服务端启动成功,端口:7777
服务端启动成功,端口:8888
服务端启动成功,端口:9999
java.nio.channels.SocketChannel[connected local=/127.0.0.1:8888 remote=/127.0.0.1:54492]:connecting
java.nio.channels.SocketChannel[connected local=/127.0.0.1:8888 remote=/127.0.0.1:54492]:大家好
连接成功!访问的端口是:8888
游客9615:新客户端加入聊天!
大家好
游客9615:大家好