基于NIO实现Discard服务器
1.服务端DisCardServer
package com.netty.redis.zookeeper.netty.unit1.oneday;
import lombok.extern.slf4j.Slf4j;
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.util.Iterator;
/**
* @Description: 基于NIO实现Discard服务器
* @ClassName: DisCardServer
* @Author zhaomx
* @Version 1.0
* @Date 2021-07-13 10:41
*/
@Slf4j
public class DisCardServer {
public static void main(String[] args) throws IOException {
// 1.获取Selector选择器,Selector是实现nio多路复用的核心
Selector selector = Selector.open();
// 2.打开套接字通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 3.设置为非阻塞
serverSocketChannel.configureBlocking(false);
// 4.绑定连接
serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 7777));
// 5.将通道注册到选择器上,并注册的IO事件为:读就绪
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
// 6.轮询已就绪的I/O就绪事件(选择键集合)
while (selector.select() > 0) {
// 7.获取选择键集合
Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
// 8.获取单个的选择键,并处理
SelectionKey selectedKey = selectedKeys.next();
// 9.判断key是具体的什么事件,不同的事件类型,做不同的处理
if (selectedKey.isAcceptable()) {
// 若选择键的IO事件是 连接就绪 事件,就获取客户端连接,此时新的客户端请求连接,需要获取链接通道,并将通道绑定到选择器上。
SocketChannel socketChannel = serverSocketChannel.accept();
// 切换为非阻塞模式
socketChannel.configureBlocking(false);
// 将该通道注册到selector选择器上
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (selectedKey.isReadable()) {
// 10-1.若选择键的IO事件是“可读”事件,读取数据
SocketChannel socketChannel = (SocketChannel) selectedKey.channel();
// 10-2.读取数据
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//10-3.把读取的数据写入到输出通道中,相当于从缓冲区中读取数据,将writeBuffer从写模式变为读模式
int length = 0;
while ((length = socketChannel.read(byteBuffer)) > 0) {
byteBuffer.flip();
log.info(new String(byteBuffer.array(), 0, length));
byteBuffer.clear();
}
socketChannel.close();
}
// 11.清除选择键
selectedKeys.remove();
}
}
// 12.关闭连接
serverSocketChannel.close();
}
}
2.客户端DisCardClient
package com.netty.redis.zookeeper.netty.unit1.oneday;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
/**
* @Description: DisCardClient客户端
* @ClassName: DisCardClient
* @Author zhaomx
* @Version 1.0
* @Date 2021-07-13 11:01
*/
@Slf4j
public class DisCardClient {
public static void main(String[] args) throws IOException {
// 1.打开套接字通道SocketChannel
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 7777));
// 2.切换成非阻塞模式
socketChannel.configureBlocking(false);
//3.不断的自旋、等待连接完成,或者做一些其他的事情
while (!socketChannel.finishConnect()) {
}
// 4、分配指定大小的缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byteBuffer.put("hello world this is discard client ".getBytes("UTF-8"));
byteBuffer.flip();
socketChannel.write(byteBuffer);
byteBuffer.clear();
//关闭通道
socketChannel.shutdownOutput();
socketChannel.close();
}
}
借鉴:https://blog.youkuaiyun.com/u010105645/article/details/106201658