public class NIOServer {
/**
* 代码中register方法源码分析
* 1,首先判断该SocketChannel中的所有SelectionKey是否有包含该selector的SelectionKey如果有直接操作该SelectionKey
* 2,如果没有找到该SelectionKey则调用Selector的register方法进行注册
* 2.1,在Selector的register方法中创建SelectionKeyImpl实例对象,
* 2.1.1,SelectionKeyImpl对象的作用就是channel与selector对象的绑定关系
* 2.2,在selector的register方法中将产生的SelectionKey绑定至selector
* 2.3,在selector的register方法中最后返回一个SelectionKey,将这个SelectionKey绑定至了channel
* 总结,本质上就是根据channel与selector对象创建一个SelectionKey对象分别绑定到channel与selector上
*/
/**
* NIO需要注意的是首先将ServerSocketChannel和关注的事件类型SelectionKey.OP_ACCEPT注册到selector上了,
* 当循环到走到isAcceptable()的分支时,其实就是循环到了ServerSocketChannel本身,
* 然后会调用ServerSocketChannel的accept看其是否有接到客户端SocketChannel,
* 如果有把客户端SocketChannel也注册到selector上生成新的SelectionKey。
* 也就是说ServerSocketChannel和客户端SocketChannel都会注册到同一selector上。
* 对于selector来说ServerSocketChannel和SocketChannel都一样只是根据感兴趣的事件类型走不同的分支而已
*/
@SuppressWarnings("unused")
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//创建服务端
InetSocketAddress serverConfig = new InetSocketAddress("localhost", 1111);//创建服务端参数
serverSocketChannel.bind(serverConfig);//绑定参数
serverSocketChannel.configureBlocking(false);//将服务端设置为非阻塞
Selector selector = Selector.open(); // 创建轮询器
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//将轮询器和类型都注册指服务器
while (true) {
int waitQty = selector.select();//获取轮询到的事件个数
if (waitQty < 1) continue;//如果没有就进入下一次循环
Set<SelectionKey> selectionKeys = selector.selectedKeys();//获取轮询器中所有的SelectionKey
Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
while (selectionKeyIterator.hasNext()) {
SelectionKey currentSelectionKey = selectionKeyIterator.next();//获取链接集合中的一个链接
if (currentSelectionKey.isAcceptable()) {
SocketChannel clientSocketChannel = serverSocketChannel.accept();
// 设置客户端为非阻塞
clientSocketChannel.configureBlocking(false);
//将接到的客户端连接SocketChannel注册到selector上
clientSocketChannel.register(selector, SelectionKey.OP_READ);
System.out.println("接收了新连接: " + clientSocketChannel.getLocalAddress() + "\n");
} else if (currentSelectionKey.isReadable()) {
//获取SelectionKey中的SocketChannel
SocketChannel clientSocketChannel = (SocketChannel) currentSelectionKey.channel();
//将客户端发过来的消息读入到buffer中
ByteBuffer buffer = ByteBuffer.allocate(256);
clientSocketChannel.read(buffer);
//将buffer中的数据转换为字符串
String result = new String(buffer.array()).trim();
System.out.println("接收信息: " + result);
if (result.equals("haha")) {
clientSocketChannel.close();
System.out.println("\n信息为haha则关闭连接");
System.out.println("\n服务器将继续运行。尝试再次运行客户端以建立新连接");
}
}
selectionKeyIterator.remove();
}
}
}
}
如果有理解不对的地方请大家多指正交流。qq17133033