Java NIO聊天室代码_客户端

服务端

public class Server {
//backlog为accept队列大小,默认值为50
private static final int BACKLOG = 1024;
private static final String IP = "127.0.0.1";
private static final int PORT = 8888;
private ServerSocketChannel serverChannel;
private Selector selector;

//构造函数
public Server() {
try {
//打开服务端通道
serverChannel = ServerSocketChannel.open();
//设置非阻塞
serverChannel.configureBlocking(false);
//绑定端口,在服务端监听
serverChannel.bind(new InetSocketAddress(IP, PORT), BACKLOG);
//打开选择器
selector = Selector.open();
//把服务端通道注册到选择器,关注的事件是接收
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
} finally {

}
}

//监听客户端
public void listen() {
try {
//循环等待客户端连接
for (; ; ) {
int readChannel = selector.select();
// if (selector.select(1000) == 0) {
// System.out.println("无连接,服务器等待...");
// continue;
// }
if (readChannel > 0) {
//关注事件集合
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
//如果是OP_ACCEPT,有新的客户端连接
if (key.isAcceptable()) {
SocketChannel channel = serverChannel.accept();
channel.configureBlocking(false);
//关联buffer
//channel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
//把通道注册到选择器,关注的事件是读
channel.register(selector, SelectionKey.OP_READ);
System.out.println(channel.getRemoteAddress() + "上线了...");
}
if (key.isReadable()) {
readClient(key);
}
//移除Selection,因为多线程,要防止重复操作
iterator.remove();
}
} else {
System.out.println("没有可用通道!");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {

}
}

//读取客户端
private void readClient(SelectionKey key) {
SocketChannel channel = null;
try {
channel = (SocketChannel) key.channel();
//获取buffer
//ByteBuffer buffer = (ByteBuffer) key.attachment();
//ByteBuffer buffer = ByteBuffer.wrap(str.getBytes());
ByteBuffer buffer = ByteBuffer.allocate(1024);
//把通道数据放入缓冲区
int count = channel.read(buffer);
if (count > 0) {
String msg = new String(buffer.array());
System.out.println("客户端:" + msg);
//转发到其他客户端
sendClient(msg, channel);
}
} catch (IOException e) {
try {
System.out.println(channel.getRemoteAddress() + "离线了...");
//取消注册
key.cancel();
//关闭通道
channel.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
} finally {

}
}

//转发给其他客户端,也就是给通道发(排除自己)
private void sendClient(String msg, SocketChannel self) throws IOException {
//遍历所有注册到选择器的通道,并排除自己
for (SelectionKey key : selector.keys()) {
Channel targetChannel = key.channel();
//排除自己
if (targetChannel instanceof SocketChannel && targetChannel != self) {
//转型
SocketChannel dest = (SocketChannel) targetChannel;
ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
//把缓冲区数据放入通道
dest.write(buffer);
}
}
}

public static void main(String[] args) throws Exception {
Server server = new Server();
server.listen();
}
}

客户端

public class Client {
private static final String IP = "127.0.0.1";
private static final int PORT = 8888;
private SocketChannel channel;
private Selector selector;
private String user;

//构造函数
public Client() throws IOException {
//打开服务端通道
channel = SocketChannel.open(new InetSocketAddress(IP, PORT));
//设置非阻塞
channel.configureBlocking(false);
//打开选择器
selector = Selector.open();
//把通道注册到选择器,关注的事件是读
channel.register(selector, SelectionKey.OP_READ);
user = channel.getLocalAddress().toString();
System.out.println(user + "已连接...");
}

//向服务器发送消息
private void sendServer(String msg) {
msg = user + ":" + msg;
ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
//把缓冲区数据放入通道
try {
channel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}

//读取服务器消息
private void readServer() {
try {
//for (; ; ) {
int readChannel = selector.select();
//判断有效通道
if (readChannel > 0) {
//关注事件集合
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
//如果是可读的
if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
channel.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
//把通道数据放入缓冲区
channel.read(buffer);
System.out.println(new String(buffer.array()));
}
//移除Selection,因为多线程,要防止重复操作
iterator.remove();
}
} else {
System.out.println("没有可用通道!");
}
//}
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception {
Client client = new Client();
//client.readServer();
//每隔2秒,读取服务端数据
new Thread(() -> {
while (true) {
client.readServer();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();

//发送数据给服务端
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String s = scanner.nextLine();
client.sendServer(s);
}
}
}