服务器
public static void main(String[] args) {
System.out.println("服务器已启动,等待连接......");
try {
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.configureBlocking(false);
serverSocket.bind(new InetSocketAddress("localhost", 8095));
//注册OP_ACCEPT事件(即监听该事件,如果有客户端发来连接请求,则该键在select()后被选中)
Selector selector = Selector.open();
serverSocket.register(selector, SelectionKey.OP_ACCEPT);
//轮询服务
while (true) {
//选择准备好的事件
selector.select();
//已选择的键集
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
//处理已选择键集事件
while (it.hasNext()) {
SelectionKey key = it.next();
//处理掉后将键移除,避免重复消费(因为下次选择后,还在已选择键集中)
it.remove();
//处理连接请求
if (key.isAcceptable()) {
//处理请求
SocketChannel socket = serverSocket.accept();
socket.configureBlocking(false);
//注册read,监听客户端发送的消息
socket.register(selector, SelectionKey.OP_READ);
//keys为所有键,除掉serverSocket注册的键就是已连接socketChannel的数量
String message = "【服务器】------连接成功 你是第" + (selector.keys().size() - 1) + "个用户";
//向客户端发送消息
socket.write(ByteBuffer.wrap(message.getBytes()));
InetSocketAddress address = (InetSocketAddress) socket.getRemoteAddress();
System.out.println("【客戶端】" + address.getPort() + "已连接");
}
if (key.isReadable()) {
SocketChannel socket = (SocketChannel) key.channel();
InetSocketAddress address = (InetSocketAddress) socket.getRemoteAddress();
ByteBuffer bf = ByteBuffer.allocate(1024 * 4);
int len = 0;
byte[] res = new byte[1024 * 4];
StringBuilder meeage = new StringBuilder("【服务器】已接收消息【");
try {
while ((len = socket.read(bf)) != 0) {
bf.flip();
bf.get(res, 0, len);
System.out.println("【客户端" + address.getPort() + "】:" + new String(bf.array(), 0, len));
meeage.append(new String(bf.array(), 0, len));
}
meeage.append("】");
socket.write(ByteBuffer.wrap(meeage.toString().getBytes(StandardCharsets.UTF_8)));
bf.clear();
} catch (IOException e) {
key.cancel();
socket.close();
System.out.println("【客戶端】" + address.getPort() + "已断开");
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
客户端
public static void main(String[] args) {
System.out.println("客户端已启动,正在连接......");
try {
SocketChannel socket = SocketChannel.open();
socket.configureBlocking(false);
Selector selector = Selector.open();
socket.register(selector, SelectionKey.OP_CONNECT);
socket.connect(new InetSocketAddress("localhost", 8095));
//开启控制台输入监听
new ChatThread(selector, socket).start();
//轮询处理
while (true) {
if (socket.isOpen()) {
//在注册的键中选择已准备就绪的事件
selector.select();
//已选择键集
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
//处理准备就绪的事件
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
//删除当前键,避免重复消费
iterator.remove();
//连接
if (key.isConnectable()) {
//在非阻塞模式下connect也是非阻塞的,所以要确保连接已经建立完成
while (!socket.finishConnect()) {
System.out.println("连接中");
}
socket.register(selector, SelectionKey.OP_READ);
}
if (key.isWritable()) {
//发送消息给服务端
socket.write((ByteBuffer) key.attachment());
socket.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable()) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 4);
int len = 0;
try {
if ((len = socket.read(byteBuffer)) > 0) {
System.out.println(new String(byteBuffer.array(), 0, len));
}
} catch (IOException e) {
System.out.println("服务器已关闭");
key.cancel();
socket.close();
}
}
}
} else {
break;
}
}
} catch (IOException e) {
System.out.println("客户端异常");
}
}