在学习nio入门前,请先学习前一篇文章,理清nio三大组件的关系
图解关系:
说明:
当客户端连接时,会通过ServerSocketChannel
,得到SocketChannel将socketChannel注册到Selector上,并且返回一个
selectorKey,该SelectorKey会和Selector关联selector进行监听select方法,返回有事件发生的通道个数
进一步得到各个SelectKey
再通过SelectKey,反向获取channel
最后通过channel完成对应的事件
服务端:
public static void main(String[] args) throws IOException {
//创建serverSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//创建selector对象
Selector selector = Selector.open();
//绑定端口6666,在服务器端监听
serverSocketChannel.socket().bind(new InetSocketAddress(6666));
//设置非阻塞
serverSocketChannel.configureBlocking(false);
//把ServerSocketChannel注册到Selector
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//循环等待客户端请求
while (true) {
if (selector.select(1000) == 0) {
System.out.println("服务器等待了1秒,无连接");
continue;
}
//获取selectorKey集合
Set<SelectionKey> selectionKeys = selector.selectedKeys();
//遍历集合
for (SelectionKey key : selectionKeys) {
//反向获取到channel,根据不同事件做出处理
if (key.isAcceptable()) {//如果是连接请求
//给该客户端生成一个socketChannel
SocketChannel channel = serverSocketChannel.accept();
//将当前的channel注册到selector上
channel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
}
if (key.isReadable()) {//读的请求
//获取到该channel
SocketChannel channel = (SocketChannel) key.channel();
//获取buffer
ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
channel.read(byteBuffer);
System.out.println("from 客户端" + new String(byteBuffer.array()));
}
//最后移出
selectionKeys.remove(key);
}
}
}
客户端:
public static void main(String[] args) throws IOException {
SocketChannel socketChannel=SocketChannel.open();
//非阻塞
socketChannel.configureBlocking(false);
//提供服务端的ip和端口
InetSocketAddress address=new InetSocketAddress("127.0.0.1",6666);
//连接服务器
if(!socketChannel.connect(address)){
while(!socketChannel.finishConnect()){
System.out.println("因为连接需要事件,可以做其他的事情");
}
}else {
//连接成功了
String str="hello world";
ByteBuffer byteBuffer=ByteBuffer.wrap(str.getBytes());
//将数据写入channel
socketChannel.write(byteBuffer);
}
}