NIO-实现聊天室
实现步骤:建立一个服务端和客户端
服务端
1、建立一个服务端
2、创建一个Selector选择器
3、创建一个Channel通道
4、绑定通道的监听端口
5、监听是否有新状态就去处理业务
public class TimServer {
public static void main(String[] args) throws IOException {
new TimServer().startServer();
}
public void startServer() throws IOException {
//创建选择器
Selector selector = Selector.open();
//创建通道
ServerSocketChannel ssc = ServerSocketChannel.open();
//为通道绑定端口
ssc.bind(new InetSocketAddress(8888));
//设置为非阻塞通道
ssc.configureBlocking(false);
//把通道注册到选择器 加上感兴趣的事件
ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动成功!");
//循环监听
while (true) {
Set key = selector.selectedKeys();
Iterator<SelectionKey> iterable = key.iterator();
int readChannels = selector.select();
while (iterable.hasNext()) {
SelectionKey next = iterable.next();
//移除当前集合的key
iterable.remove();
if (next.isAcceptable()) {
accept(ssc,selector);
} else if (next.isReadable()) {
readable(selector,next);
}
}
}
}
/**
* 处理连接状态
* */
public void accept(ServerSocketChannel serverSocketChannel,Selector selector) throws IOException {
//接入ServerSocketChannel
SocketChannel socketChannel = serverSocketChannel.accept();
//设置为非阻塞模式
socketChannel.configureBlocking(false);
//把channel注册到选择器上
socketChannel.register(selector,SelectionKey.OP_READ);
//回复信息
socketChannel.write(Charset.forName("UTF-8").encode("欢迎来到聊天室~"));
}
/**
* 处理可读状态
* */
public void readable(Selector selector,SelectionKey selectionKey) throws IOException {
//从SelectKey获取就绪的通道
SocketChannel socketChannel= (SocketChannel) selectionKey.channel();
//创建buffer
ByteBuffer buffer=ByteBuffer.allocate(1024);
//循环读取客户端信息
StringBuilder stringBuilder=new StringBuilder();
int readLength = socketChannel.read(buffer);
if (readLength>0){
//切换读模式
buffer.flip();
//读取内容
stringBuilder.append(Charset.forName("UTF-8").decode(buffer));
}
//把通道注册到选择器上
socketChannel.register(selector,SelectionKey.OP_READ);
//广播到其他客户端
if (stringBuilder.length()>0){
System.out.println(stringBuilder);
castClient(selector,socketChannel, String.valueOf(stringBuilder));
}
}
/**
* 广播到其他客户端
* */
public void castClient(Selector selector,SocketChannel socketChannel,String message) throws IOException {
// 获取所有已经接入的channel
Set<SelectionKey> selectionKeySet=selector.keys();
//循环所有广播消息
for (SelectionKey selectionKey : selectionKeySet) {
//获取每个channel
Channel tarChannel=selectionKey.channel();
//不需要给自己发送
if(tarChannel instanceof SocketChannel&&tarChannel!=socketChannel){
((SocketChannel) tarChannel).write(Charset.forName("UTF-8").encode(message));
}
}
}
}
客户端
public class TimClient {
public static void main(String[] args) throws IOException {
new TimClient().startClient("ylc");
}
public void startClient(String name) throws IOException {
//连接服务器
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress( 8888));
//接收服务端响应
Selector selector = Selector.open();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
//创建线程 获取服务器的消息
new Thread(new ClientThread(selector)).start();
//向服务器发送消息 控制台输入
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String msg = scanner.nextLine();
if (msg.length() > 0) {
socketChannel.write(Charset.forName("UTF-8").encode(name+":"+msg));
}
}
}
}
实现效果: