服务端代码示例
package com.example.nettytest.nio.day3;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
* @description: Selector处理accept事件 代码示例
* @author: xz
* @create: 2022-09-01
*/
@Slf4j
public class Test2Server {
public static void main(String[] args) {
nioSelectorAcceptServer();
}
/**
* Selector处理accept事件 方法
* */
private static void nioSelectorAcceptServer(){
try (ServerSocketChannel channel = ServerSocketChannel.open()) {//1、创建服务器
//绑定监听端口
channel.bind(new InetSocketAddress(8080));
//设置为非阻塞模式
channel.configureBlocking(false);
System.out.println("channel=="+channel);
/**
* 2、创建Selector,管理多个channel
*/
Selector selector = Selector.open();
/**
* 3、建立Selector与channel的联系(也称为注册)
* key只关注事件,绑定的事件类型4种,connect - 客户端连接成功时触发;accept - 服务器端成功接受连接时触发; read - 数据可读入时触发;write - 数据可写出时触发,
* */
channel.register(selector, SelectionKey.OP_ACCEPT);
while(true){
/**
* 3、select 方法, 没有事件发生,线程阻塞,有事件,线程才会恢复运行
* select 在事件未处理时,它不会阻塞
*/
int count = selector.select();
log.debug("select count: {}", count);
// 获取所有事件
Set<SelectionKey> keys = selector.selectedKeys();
// 遍历所有事件,逐一处理
Iterator<SelectionKey> iterator = keys.iterator();
//遍历所有事件,逐一处理
while(iterator.hasNext()){
SelectionKey key = iterator.next();
log.info("key===={}",key);
// 判断事件类型,如果事件类型是 accept - 服务器端成功接受连接时触发;
if (key.isAcceptable()) {
//channel中有哪些key
ServerSocketChannel c = (ServerSocketChannel) key.channel();
//必须处理 selector 上的 channel
SocketChannel sc = c.accept();
log.debug("sc==={}", sc);
}
// 处理完毕,必须将事件移除
iterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端代码示例
package com.example.nettytest.nio.day3;
import java.io.IOException;
import java.net.Socket;
/**
* @description:
* @author: xz
* @create: 2022-09-01
*/
public class Test2Client {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 8080)) {
System.out.println(socket);
socket.getOutputStream().write("hello world".getBytes());
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
先启动服务端
由下图输出结果可知,由于没有事件发生,再select 方法处,线程阻塞。
再启动客户端
再查看服务端控制台输出
由下图输出结果可知,由于有事件发生,再select 方法处,线程会恢复运行。