浏览 1628 次
锁定老帖子 主题:NIO Web服务器示例
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-06-25
最后修改:2011-02-13
2 selector服务accept和read 3 accept selector作为生产者把获得的请求放入队列 4 当获得read信号时,selector建立工作任务线程worker,并提交给系统线程池 5 worker线程排队后在线程池中执行,把协议头读入缓冲区,然后解析,处理,响应,关闭连接 import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Date; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class WebServer { private static WebServer svr = new WebServer(); private WebServer(){} public static WebServer getInstance(){return svr;} public void init() throws Exception{ ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); Selector sel = Selector.open(); ssc.socket().bind(new InetSocketAddress(8088)); ssc.register(sel, SelectionKey.OP_ACCEPT); ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); while (!Thread.interrupted()) { sel.select(); Set<SelectionKey> readyKeys = sel.selectedKeys(); Iterator<SelectionKey> iter = readyKeys.iterator(); while (iter.hasNext()) { SelectionKey sk = iter.next(); if (sk.isAcceptable()) { SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(sel, SelectionKey.OP_READ).attach(new Worker(sc)); }else if (sk.isValid() && sk.isReadable()) { Worker worker = (Worker)sk.attachment(); if(!worker.isRunning()) es.execute(worker); } readyKeys.clear(); } } } private static class Worker implements Runnable{ ByteBuffer bb = ByteBuffer.allocateDirect(1024); SocketChannel sc = null; State state = State.IDLE; private static enum State{ IDLE, RUNNING } public Worker(SocketChannel sc){ Thread.currentThread().setName(sc.toString()); this.sc = sc; } private void dispose() throws IOException{ state = State.RUNNING; sc.read(bb); bb.flip(); byte[] bs = new byte[bb.limit()]; bb.get(bs); System.err.println(new String(bs)); bb.clear(); StringBuilder sb = new StringBuilder(); sb.append("HTTP/1.1 200 OK").append("\n").append("Date:" + new Date()).append("\n"); sb.append("Server:NIO Server By Yi Yang\n\n"); bb.put(sb.toString().getBytes()); bb.put("OK".getBytes()); bb.flip(); sc.write(bb); bb.clear(); sc.close(); } public synchronized boolean isRunning(){ return state == State.RUNNING; } public synchronized void run() { try { if(state == State.IDLE) dispose(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) throws Exception { WebServer server = WebServer.getInstance(); server.init(); } } ===============06/27/10 如何解析header?,以行为单位读取,按照header敏感的关键字进行匹配 对于首行取得对方调用的方法GET/POST 地址 和协议版本 然后根据用户的配置,和解析地址请求,获得响应的servlet,并把通过反射+默认构造函数构造这个servlet,解析地址参数等设置到对象httpservletrequest和httpservletresponse中,然后通过反射invoke对应的get/post/put/delete等方法,并把封装的两个对象作为参数传进去,同时在response的header中传递一个cookie作为session的依据。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |