Servlet API 和 NIO: 最终组合在一起
2009-11-08 00:00:00 来源:WEB开发网示例服务器
示例服务器展示了 Servlet API 和 NIO 不兼容的生产者/消费者解决方案。该服务器与 Servlet API 非常相似,可以为成熟的基于 NIO 应用程序服务器提供 POC (proof of concept),是专门编写来衡量 NIO 相对于标准 Java I/O 的性能的。它处理简单的 HTTP get 请求,并支持来自客户机的 Keep-Alive 连接。这是重要的,因为多路复用 I/O 只证明在要求服务器处理大量打开的 scoket 连接时是有意的。
该服务器被分成两个包: org.sse.server 和 org.sse.http 包中有提供主要 服务器 功能的类,比如如下的一些功能:接收新客户机连接、阅读消息和生成工作线程以处理请求。 http 包支持 HTTP 协议的一个子集。详细阐述 HTTP 超出了本文的范围。
现在让我们来看一下 org.sse.server 包中一些最重要的类。
Server 类
Server 类拥有多路复用循环 —— 任何基于 NIO 服务器的核心。在清单 1 中,在服务器接收新客户机或检测到正把可用的字节写到打开的 socket 前, select() 的调用阻塞了。这与标准 Java I/O 的主要区别是,所有的数据都是在这个循环中读取的。通常会把从特定 socket 中读取字节的任务分配给一个新线程。使用 NIO 选择器事件驱动方法,实际上可以用单个线程处理成千上万的客户机,不过,我们还会在后面看到线程仍有一个角色要扮演。
每个 select() 调用返回一组事件,指出新客户机可用;新数据准备就绪,可以读取;或者客户机准备就绪,可以接收响应。server 的 handleKey() 方法只对新客户机( key.isAcceptable() )和传入数据 ( key.isReadable() ) 感兴趣。到这里,工作就结束了,转入 ServerEventHandler 类。
清单 1. Server.java 选择器循环public void listen() {
SelectionKey key = null;
try {
while (true) {
selector.select();
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
key = (SelectionKey) it.next();
handleKey(key);
it.remove();
}
}
} catch (IOException e) {
key.cancel();
} catch (NullPointerException e) {
// NullPointer at sun.nio.ch.WindowsSelectorImpl, Bug: 4729342
e.printStackTrace();
}
}
更多精彩
赞助商链接