使用 Selector 多路複用,單線程處理海量連接。核心組件:
Selector 與 select() 循環,管理 NioSession 註冊/處理。SelectableChannel、interestOps、process() 邏輯。ServerSocketChannel,OP_ACCEPT,接受連接並創建 NioEchoSession。SocketChannel,狀態機處理讀/寫循環。while (_run) {
_sel.select();
for (SelectionKey key : _sel.selectedKeys()) {
((NioSession) key.attachment()).process();
key.cancel(); // 或 itr.remove()
}
// 註冊新增 Session
synchronized (_added) {
for (NioSession s : _added) {
SelectionKey key = s.channel().register(_sel, s.interestOps(), s);
s.registered(key);
}
_added.clear();
}
}
public abstract class EchoState {
abstract void process(NioEchoSession s) throws IOException;
abstract int interestOps();
static EchoState readState() { return _read; }
static EchoState writeState() { return _write; }
}
class ReadState extends EchoState {
void process(NioEchoSession s) {
int n = s._channel.read(s._buf);
if (n == -1) { s.close(); return; }
if (n > 0) { s._buf.flip(); s.setState(writeState()); }
}
int interestOps() { return SelectionKey.OP_READ; }
}
class WriteState extends EchoState {
void process(NioEchoSession s) {
s._channel.write(s._buf);
if (!s._buf.hasRemaining()) { s._buf.clear(); s.setState(readState()); }
}
int interestOps() { return SelectionKey.OP_WRITE; }
}
NioEchoSession 委派 process() 給當前 EchoState,setState() 切換狀態並更新 interestOps。
public class NioEchoServer implements Runnable {
public void run() {
ServerSocketChannel serv = ServerSocketChannel.open();
serv.socket().bind(new InetSocketAddress(7));
serv.configureBlocking(false);
NioWorker worker = new NioWorker(Selector.open());
worker.add(new NioServerSession(serv, worker));
worker.run(); // 阻塞循環
}
public synchronized void shutdown() { worker.stop(); wait(); }
public static void main(String[] args) { new NioEchoServer().run(); }
}
telnet localhost 7。NioSession,無需修改 NioWorker。if-else。