1. 简介
IO多路复用(multiplexing)属于同步IO网络模型
是以Reactor模式实现
常见的IO多路复用应用有:select、poll、epoll
有关于select的应用方式,请参阅[C语言] 基于Linux的一对一Socket简易聊天程序实例
本篇文章采用Java的NIO框架来实现单线程的IO多路复用
2. Reactor模式的组成角色
1. Reactor:负责派发IO事件给对应的角色处理。为了监听IO事件,select必须实现在Reactor中。
2. Acceptor:负责接受client的连线,然后给client绑定一个Handler并注册IO事件到Reactor上监听。
3. Handler:负责处理与client交互的事件或行为。通常因为Handler要处理与所对应client交互的多个事件或行为,为了简化设计,会以状态模式来实现Handler。
3. 代码实现
[TCPReactor.java]
-
- package server;
-
- 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.util.Iterator;
- import java.util.Set;
-
- public class TCPReactor implements Runnable {
-
- private final ServerSocketChannel ssc;
- private final Selector selector;
-
- public TCPReactor(int port) throws IOException {
- selector = Selector.open();
- ssc = ServerSocketChannel.open();
- InetSocketAddress addr = new InetSocketAddress(port);
- ssc.socket().bind(addr);
- ssc.configureBlocking(false);
- SelectionKey sk = ssc.register(selector, SelectionKey.OP_ACCEPT);
- sk.attach(new Acceptor(selector, ssc));
- }
-
- @Override
- public void run() {
- while (!Thread.interrupted()) {
- System.out.println("Waiting for new event on port: " + ssc.socket().getLocalPort() + "...");
- try {
- if (selector.select() == 0)
- continue;
- } catch (IOException e) {
-
- e.printStackTrace();
- }
- Set<SelectionKey> selectedKeys = selector.selectedKeys();
- Iterator<SelectionKey> it = selectedKeys.iterator();
- while (it.hasNext()) {
- dispatch((SelectionKey) (it.next()));
- it.remove();
- }
- }