![c1966158d44b3d084f42aa3f7ed87e9e.png](https://img-blog.csdnimg.cn/img_convert/c1966158d44b3d084f42aa3f7ed87e9e.png)
直接上代码吧!
客户端
package com.cn.niochat;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Scanner;
/**
* 用Java实现nio的客户端
*/
public class NioClient {
public void start() throws IOException {
/**
* 链接服务器端
*/
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",8000));
//向服务器端发送数据
//从命令行获取数据,获取键盘的输入
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()){
//获取这一行数据
String request = scanner.nextLine();
//如果有数据,则发送,且数据不为空
if(request != null && request.length() > 0){
socketChannel.write(Charset.forName("UTF-8").encode(request));
}
}
}
public static void main(String[] args) throws IOException {
NioClient nioClient = new NioClient();
nioClient.start();
}
}
服务器端
package com.cn.niochat;
import java.io.IOException;
import java.net.InetSocketAddress;
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.Iterator;
import java.util.Set;
/**
* 多人聊天室服务端
*/
public class NioServer {
/**
* 创建服务端的链接
*/
public void start() throws IOException {
//1.创建selector
Selector selector = Selector.open();
//2.通过serverSocketChannel创建channel通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//3.为channel通道绑定监听地址
serverSocketChannel.bind(new InetSocketAddress(8000));
//4.设置channel为非阻塞模式
serverSocketChannel.configureBlocking(false);
//5.将channel注册到selector上,监听链接事件
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//6.循环等待新链接的接入
while (true){
//获取selector的数量
int readyChannels = selector.select();
//如果这个数量等于0表示没有准备好的,则继续循环,不执行下面的代码
if (readyChannels == 0) continue;
//如果有可用的数量,selector会将所有的channel放入到slectionKey的set集合中,从中获取
Set<SelectionKey> selectionKeys = selector.selectedKeys();
//然后通过迭代器的方式将每个链接展示出来
Iterator iterator = selectionKeys.iterator();
//如果存在,则继续
while (iterator.hasNext()){
//获取selectionKey实例
SelectionKey selectionKey = (SelectionKey) iterator.next();
//移除selectionKey
iterator.remove();
//7.根据不同的就绪状态,去处理不同的业务逻辑
//如果是接入事件
if(selectionKey.isAcceptable()){
acceptHandler(serverSocketChannel,selector);
}
//如果是可读事件
if(selectionKey.isReadable()){
readHandler(selectionKey,selector);
}
}
}
}
/**
* 接入事件
*/
private void acceptHandler(ServerSocketChannel serverSocketChannel,Selector selector) throws IOException {
//如果是接入事件,创建socketChannel
SocketChannel socketChannel = serverSocketChannel.accept();
//将socketChannel设置为非阻塞模式
socketChannel.configureBlocking(false);
//将channel注册到selector上,监听可读事件
socketChannel.register(selector,SelectionKey.OP_READ);
//回复客户端信息
socketChannel.write(Charset.forName("UTF-8").encode("您与聊天室其他人都不是朋友关系,请注意隐私安全"));
}
/**
* 可读事件
*/
private void readHandler(SelectionKey selectionKey,Selector selector) throws IOException {
//要从selectionKey中获取到已经就绪的channel
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
//创建buffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//循环读取客户端信息
String request = "";
while (socketChannel.read(byteBuffer) > 0){
//将bufer转成读模式
byteBuffer.flip();
//读取buffer中的内容
request += Charset.forName("UTF-8").decode(byteBuffer);
}
/**
* 将channel再次注册到selector 上,监听他的可读事件
*/
socketChannel.register(selector,SelectionKey.OP_READ);
//将消息广播给其他变量
if(request.length() > 0){
System.out.println(request);
}
}
public static void main(String[] args) throws IOException {
NioServer nioServer = new NioServer();
nioServer.start();
}
}
总结
这个还是挺好玩的,可以用它实现一个聊天室的功能,上面的代码就是实现了一个基本的聊天,当然了,点击关注不迷路哦,写这篇文章主要是为了后面写kafka源码阅读作准备的。