java
@Slf4j
public class NioServer {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
serverSocketChannel.bind(new InetSocketAddress(8000));
while (true) {
selector.select();
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
if(iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
iterator.remove();
//与客户端建立连接
if(selectionKey.isAcceptable()) {
//因为ServerSocketChannel只有一个,可以直接使用
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
SelectionKey acceptKey = socketChannel.register(selector, 0, null);
acceptKey.interestOps(SelectionKey.OP_READ);
//向客户端发大量数据
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5000000; i++) {
sb.append("a");
}
ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(sb.toString());
//返回实际写的字节数
int write = socketChannel.write(byteBuffer);
log.info("write1={}", write);
if(byteBuffer.hasRemaining()) {
//添加关注写事件
acceptKey.interestOps(acceptKey.interestOps() + SelectionKey.OP_WRITE);
//把未写完的数据挂到selectKey上
acceptKey.attach(byteBuffer);
}
} else if(selectionKey.isWritable()) {
ByteBuffer byteBuffer = (ByteBuffer)selectionKey.attachment();
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
int write = socketChannel.write(byteBuffer);
log.info("write2={}", write);
//清理操作
if(!byteBuffer.hasRemaining()) {
selectionKey.attach(null);//清除附件ByteBuffer
//不需要关注write事件
selectionKey.interestOps(selectionKey.interestOps() - SelectionKey.OP_WRITE);
}
}
}
}
}
}
java
@Slf4j
public class NioClient {
public static void main(String[] args) throws IOException {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("localhost", 8000));
long totalCount = 0;
while (true) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024 * 1024);
int read = socketChannel.read(byteBuffer);
totalCount += read;
log.info("totalCount={}", totalCount);
byteBuffer.clear();
}
}
}