服务端:
package nioChat;/*
*@author:
*@time
*/
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Optional;
import java.util.Set;
public class Server {
private final static int DEFAULT_PORT = 8888;
private ServerSocketChannel server;
private Selector selector;
private ByteBuffer rBuffer;
private ByteBuffer wBuffer;
private Charset charset = Charset.forName("utf-8");
private int port;
public Server() {
this.port = DEFAULT_PORT;
rBuffer = ByteBuffer.allocate(1024);
wBuffer = ByteBuffer.allocate(1024);
}
public Server(int port) {
rBuffer = ByteBuffer.allocate(1024);
wBuffer = ByteBuffer.allocate(1024);
this.port = port;
}
public static void main(String[] args) {
Server server = new Server(7777);
server.start();
}
public void start() {
try {
server = ServerSocketChannel.open();
server.configureBlocking(false);
server.socket().bind(new InetSocketAddress(port));
selector = Selector.open();
server.register(selector, SelectionKey.OP_ACCEPT);
Optional.of("服务启动.")
.ifPresent(System.out::println);
while (true) {
//一直监听是否有请求进入
if (selector.select() > 0) {
Set<SelectionKey> selectionKeys = selector.selectedKeys();
for (SelectionKey key : selectionKeys) {
handles(key);
}
//处理完后清空select中监听到的值
selectionKeys.clear();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handles(SelectionKey key) throws IOException {
//accept事件,与客户端建立了联系
if (key.isAcceptable()) {
SocketChannel client = ((ServerSocketChannel) key.channel()).accept();
//默认阻塞关闭
client.configureBlocking(false);
//read事件注册
client.register(selector, SelectionKey.OP_READ);
Optional.of(getClientName(client) + "上线.")
.ifPresent(System.out::println);
}
//read事件,读取客户端发送的消息
else if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
//接收用户输入
String msg = receive(client);
//转发给其他客户
if (msg != null && (!msg.equals(""))) {
send(client, msg);
client.register(selector, SelectionKey.OP_READ);
//检查用户是否退出
if (exit(msg)) {
Optional.of(getClientName(client) + "下线.")
.ifPresent(System.out::println);
key.cancel();
selector.wakeup();
}
}
}
}
private void send(SocketChannel client, String msg) throws IOException {
Set<SelectionKey> keys = selector.keys();
for (SelectionKey key : keys) {
Channel connectedChannel = key.channel();
if (connectedChannel instanceof ServerSocketChannel) {
continue;
}
if (msg.equals("exit") && client.equals(connectedChannel)) {
wBuffer.clear();
wBuffer.put(charset.encode("exit"));
wBuffer.flip();
while (wBuffer.hasRemaining()) {
((SocketChannel) connectedChannel).write(wBuffer);
}
}
if (key.isValid() && !client.equals(connectedChannel)) {
wBuffer.clear();
wBuffer.put(charset.encode(getClientName(client) + ":" + msg));
wBuffer.flip();
while (wBuffer.hasRemaining()) {
((SocketChannel) connectedChannel).write(wBuffer);
}
}
}
}
private String receive(SocketChannel client) throws IOException {
rBuffer.clear();
while (client.read(rBuffer) > 0) ;
rBuffer.flip();
String msg = String.valueOf(charset.decode(rBuffer));
System.out.println(getClientName(client) + ":" + msg);
return msg;
}
private boolean exit(String msg) {
if (null != msg && msg.equals("exit")) {
return true;
}
return false;
}
private String getClientName(SocketChannel client) {
return "客户端[" + client.socket().getPort() + "]";
}
}
客户端:
package nioChat;/*
*@author:
*@time
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
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.nio.charset.Charset;
import java.util.Optional;
import java.util.Set;
public class Client {
private SocketChannel client;
private Selector selector;
private ByteBuffer rBuffer;
private ByteBuffer wBuffer;
private String host;
private int port;
private boolean isRunning = true;
private Charset charset = Charset.forName("utf-8");
public Client(String host, int port) {
this.host = host;
this.port = port;
rBuffer = ByteBuffer.allocate(1024);
wBuffer = ByteBuffer.allocate(1024);
}
public static void main(String[] args) {
Client client = new Client("localhost", 7777);
client.start();
}
private void start() {
try {
client = SocketChannel.open();
client.configureBlocking(false);
selector = Selector.open();
//客户端监听连接事件
client.register(selector, SelectionKey.OP_CONNECT);
client.connect(new InetSocketAddress(host, port));
Optional.of("客户端上线.")
.ifPresent(System.out::println);
//一直监听是否有请求进入
while (isRunning) {
if(selector.select()>0){
Set<SelectionKey> selectionKeys = selector.selectedKeys();
for (SelectionKey key : selectionKeys) {
handles(key);
}
//处理完后清空select中监听到的值
selectionKeys.clear();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handles(SelectionKey key) throws IOException {
//connect--连接就绪事件
if (key.isConnectable()) {
SocketChannel client = (SocketChannel) key.channel();
if (client.isConnectionPending()) {
client.finishConnect();
//处理用户输入
send(client);
}
client.register(selector, SelectionKey.OP_READ);
}
//read--服务器转发事件
else if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
receive(client);
}
}
private void send(SocketChannel client) {
new Thread(() -> {
BufferedReader ips = new BufferedReader(new InputStreamReader(System.in));
while (isRunning) {
try {
String msg = ips.readLine();
if (msg != null) {
wBuffer.clear();
wBuffer.put(charset.encode(msg));
wBuffer.flip();
while (wBuffer.hasRemaining()) {
client.write(wBuffer);
}
if (msg.equals("exit")) {
isRunning = false;
}
}
} catch (IOException e) {
System.out.println("发送故障.");
e.printStackTrace();
isRunning = false;
}
}
}).start();
}
private String receive(SocketChannel client) throws IOException {
rBuffer.clear();
while (client.read(rBuffer) > 0) ;
rBuffer.flip();
String msg = String.valueOf(charset.decode(rBuffer));
if (msg.equals("exit")) {
isRunning = false;
Optional.of("客户端关闭.")
.ifPresent(System.out::println);
} else {
Optional.of(msg)
.ifPresent(System.out::println);
}
return msg;
}
}