通过SocketChannel 和 ServerSocketChannel 写一个阻塞的网络IO操作
package edu.xcdq;
/**
* @qvthor liuwenzheng
* @date 2021/5/18 20:50
*/
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;
public class De {
public static void main(String[] args) throws Exception {
int port = 8000;
// 通过open()方法找到Selector
Selector selector = Selector.open();
// 打开服务器的通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 服务器配置为非阻塞
serverSocketChannel.configureBlocking(false);
ServerSocket serverSocket = serverSocketChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
// 进行服务的绑定
serverSocket.bind(address);
// 注册到selector,等待连接
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器运行,端口:" + port);
// 数据缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while (true) {
if ((selector.select()) > 0) {
// 选择一组键,并且相应的通道已经准备就绪
// 取出全部生成的key
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
if (key.isAcceptable()) {
acceptable(key, byteBuffer, selector);
} else if (key.isReadable() && key.isValid()) {
readable(selector, byteBuffer, key);
} else if (key.isWritable() && key.isValid()) {
writable(selector, byteBuffer, key);
}
}
// 清除全部的key
selectedKeys.clear();
}
}
}
public static void writable(Selector selector, ByteBuffer byteBuffer, SelectionKey key)
throws IOException, ClosedChannelException {
SocketChannel client = (SocketChannel) key.channel();
byteBuffer.clear();
// 向缓冲区中设置内容
byteBuffer.put(("欢迎学习NIO教程").getBytes());
byteBuffer.flip();
// 输出内容
client.write(byteBuffer);
client.register(selector, SelectionKey.OP_READ);
}
public static void readable(Selector selector, ByteBuffer byteBuffer, SelectionKey key)
throws IOException, ClosedChannelException {
SocketChannel client = (SocketChannel) key.channel();
byteBuffer.clear();
// 读取内容到缓冲区中
int readSize = client.read(byteBuffer);
if (readSize > 0) {
System.out.println("服务器端接受客户端数据:" + new String(byteBuffer.array(), 0, readSize));
client.register(selector, SelectionKey.OP_WRITE);
}
}
public static void acceptable(SelectionKey key, ByteBuffer byteBuffer, Selector selector) throws IOException {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
// 接收新连接 和BIO写法类是都是accept
SocketChannel client = server.accept();
// 配置为非阻塞
client.configureBlocking(false);
byteBuffer.clear();
// 向缓冲区中设置内容
byteBuffer.put(("当前的时间为:" + new Date()).getBytes());
byteBuffer.flip();
// 输出内容
client.write(byteBuffer);
client.register(selector, SelectionKey.OP_READ);
}
}
}
客户端
package edu.xcdq;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;
/**
* @qvthor liuwenzheng
* @date 2021/5/18 16:16
*/
public class SelectorServiceDemo {
public static void main(String[] args) throws Exception {
int port = 8000;
//通过open()方法找到Selector
Selector selector = Selector.open();
//打开服务器的通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 服务器配置为非阻塞
serverSocketChannel.configureBlocking(false);
ServerSocket serverSocket = serverSocketChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
//进行服务器绑定
serverSocket.bind(address);
//注册到selector,等待链接
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器运行,端口:"+port);
//数据缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while (true){
if (selector.select()>0){
//选择一组键,并且相应的通道已经准备就绪
//去除全部生成的key
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectionKeys.iterator();
while (iter.hasNext()){
SelectionKey key = iter.next();
if (key.isAcceptable()){
acceptable(key,byteBuffer,selector);
}else if (key.isReadable()&& key.isValid()){
readable(selector,byteBuffer,key);
}else if (key.isWritable()&& key.isValid()){
writable(selector,byteBuffer,key);
}
}
//清除全部的key
selectionKeys.clear();;
}
}
}
public static void writable(Selector selector, ByteBuffer byteBuffer, SelectionKey key)
throws IOException {
SocketChannel client =(SocketChannel) key.channel();
byteBuffer.clear();
//向缓冲区中设置内容
byteBuffer.put(("欢迎学习NIO教程").getBytes());
byteBuffer.flip();
//输出内容
client.write(byteBuffer);
client.register(selector, SelectionKey.OP_READ);
}
public static void readable(Selector selector, ByteBuffer byteBuffer, SelectionKey key)
throws IOException, ClosedChannelException {
SocketChannel client = (SocketChannel) key.channel();
byteBuffer.clear();
// 读取内容到缓冲区中
int readSize = client.read(byteBuffer);
if (readSize > 0) {
System.out.println("服务器端接受客户端数据:" + new String(byteBuffer.array(), 0, readSize));
client.register(selector, SelectionKey.OP_WRITE);
}
}
public static void acceptable(SelectionKey key, ByteBuffer byteBuffer, Selector selector) throws IOException {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
// 接收新连接 和BIO写法类是都是accept
SocketChannel client = server.accept();
// 配置为非阻塞
client.configureBlocking(false);
byteBuffer.clear();
// 向缓冲区中设置内容
byteBuffer.put(("当前的时间为:" + new Date()).getBytes());
byteBuffer.flip();
// 输出内容
client.write(byteBuffer);
client.register(selector, SelectionKey.OP_READ);
}
}