码迷,mamicode.com
首页 > 编程语言 > 详细

Java实现Http服务器(四)

时间:2015-11-24 20:37:08      阅读:261      评论:0      收藏:0      [点我收藏+]

标签:

 

 

(1)HTTPServer的监听启动

sun.net.httpserver.ServerImpl类中启动了Socket监听,ServerImpl的内部类Dispatch类启动了Http服务器的监听

 

 /* main server listener task */

    class Dispatcher implements Runnable {

        private void handleEvent (Event r) {
            ExchangeImpl t = r.exchange;
            HttpConnection c = t.getConnection();
            try {
                if (r instanceof WriteFinishedEvent) {

                    int exchanges = endExchange();
                    if (terminating && exchanges == 0) {
                        finished = true;
                    }
                    SocketChannel chan = c.getChannel();
                    LeftOverInputStream is = t.getOriginalInputStream();
                    if (!is.isEOF()) {
                        t.close = true;
                    }
                    if (t.close || idleConnections.size() >= MAX_IDLE_CONNECTIONS) {
                        c.close();
                        allConnections.remove (c);
                    } else {
                        if (is.isDataBuffered()) {
                            /* don‘t re-enable the interestops, just handle it */
                            handle (c.getChannel(), c);
                        } else {
                            /* re-enable interestops */
                            SelectionKey key = c.getSelectionKey();
                            if (key.isValid()) {
                                key.interestOps (
                                    key.interestOps()|SelectionKey.OP_READ
                                );
                            }
                            c.time = getTime() + IDLE_INTERVAL;
                            idleConnections.add (c);
                        }
                    }
                }
            } catch (IOException e) {
                logger.log (
                    Level.FINER, "Dispatcher (1)", e
                );
                c.close();
            }
        }

        public void run() {
            while (!finished) {
                try {

                    /* process the events list first */

                    while (resultSize() > 0) {
                        Event r;
                        synchronized (lolock) {
                            r = events.remove(0);
                            handleEvent (r);
                        }
                    }

                    selector.select(1000);

                    /* process the selected list now  */

                    Set<SelectionKey> selected = selector.selectedKeys();
                    Iterator<SelectionKey> iter = selected.iterator();
                    while (iter.hasNext()) {
                        SelectionKey key = iter.next();
                        iter.remove ();
                        if (key.equals (listenerKey)) {
                            if (terminating) {
                                continue;
                            }
                            SocketChannel chan = schan.accept();
                            if (chan == null) {
                                continue; /* cancel something ? */
                            }
                            chan.configureBlocking (false);
                            SelectionKey newkey = chan.register (selector, SelectionKey.OP_READ);
                            HttpConnection c = new HttpConnection ();
                            c.selectionKey = newkey;
                            c.setChannel (chan);
                            newkey.attach (c);
                            allConnections.add (c);
                        } else {
                            try {
                                if (key.isReadable()) {
                                    boolean closed;
                                    SocketChannel chan = (SocketChannel)key.channel();
                                    HttpConnection conn = (HttpConnection)key.attachment();
                                    // interestOps will be restored at end of read
                                    key.interestOps (0);
                                    handle (chan, conn);
                                } else {
                                    assert false;
                                }
                            } catch (IOException e) {
                                HttpConnection conn = (HttpConnection)key.attachment();
                                logger.log (
                                    Level.FINER, "Dispatcher (2)", e
                                );
                                conn.close();
                            }
                        }
                    }
                } catch (CancelledKeyException  e) {
                    logger.log (Level.FINER, "Dispatcher (3)", e);
                } catch (IOException e) {
                    logger.log (Level.FINER, "Dispatcher (4)", e);
                } catch (Exception e) {
                    logger.log (Level.FINER, "Dispatcher (7)", e);
                }
            }
        }

        public void handle (SocketChannel chan, HttpConnection conn)
        throws IOException
        {
            try {
                Exchange t = new Exchange (chan, protocol, conn);
                executor.execute (t);
            } catch (HttpError e1) {
                logger.log (Level.FINER, "Dispatcher (5)", e1);
                conn.close();
            } catch (IOException e) {
                logger.log (Level.FINER, "Dispatcher (6)", e);
                conn.close();
            }
        }
    }

    static boolean debug = ServerConfig.debugEnabled ();

    static synchronized void dprint (String s) {
        if (debug) {
            System.out.println (s);
        }
    }

    static synchronized void dprint (Exception e) {
        if (debug) {
            System.out.println (e);
            e.printStackTrace();
        }
    }

    Logger getLogger () {
        return logger;
    }

 

该类的初始化在sun.net.httpserver.ServerImpl的构造方法当中

ServerImpl (HttpServer wrapper, String protocol, InetSocketAddress addr, int backlog) throws IOException {
        this.protocol = protocol;
        this.wrapper = wrapper;
        this.logger = Logger.getLogger ("com.sun.net.httpserver");
        https = protocol.equalsIgnoreCase ("https");
        this.address = addr;
        contexts = new ContextList();
        schan = ServerSocketChannel.open();
        if (addr != null) {
            ServerSocket socket = schan.socket();
            socket.bind (addr, backlog);
            bound = true;
        }
        selector = Selector.open ();
        schan.configureBlocking (false);
        listenerKey = schan.register (selector, SelectionKey.OP_ACCEPT);
        dispatcher = new Dispatcher();
        idleConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
        allConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
        time = System.currentTimeMillis();
        timer = new Timer ("server-timer", true);
        timer.schedule (new ServerTimerTask(), CLOCK_TICK, CLOCK_TICK);
        events = new LinkedList<Event>();
        logger.config ("HttpServer created "+protocol+" "+ addr);
    }

 

随后在sun.net.httpserver.ServerImpl类的start方法当中,作为线程被启动

public void start () {
        if (!bound || started || finished) {
            throw new IllegalStateException ("server in wrong state");
        }
        if (executor == null) {
            executor = new DefaultExecutor();
        }
        Thread t = new Thread (dispatcher);
        started = true;
        t.start();
    }

 

import com.sun.net.httpserver.HttpServer;
private HttpServer httpServer = null; public final void init() throws IOException { this.executor = Executors.newCachedThreadPool(); final InetSocketAddress sa = new InetSocketAddress("0.0.0.0", 8080); this.httpServer = HttpServer.create(sa, 0); this.httpServer.setExecutor(this.executor); this.httpServer.createContext("/", new HttpServerHandler()); this.httpServer.start(); }

上面是使用JDK内置HttpServer的方法。

在第二篇文章中介绍过返回的默认对象是

sun.net.httpserver.HttpServerImpl对象,该对象是com.sun.net.httpserver.HttpServer对象的子类

public class HttpServerImpl extends HttpServer {

    ServerImpl server;

    HttpServerImpl () throws IOException {
        this (new InetSocketAddress(80), 0);
    }

    HttpServerImpl (
        InetSocketAddress addr, int backlog
    ) throws IOException {
        server = new ServerImpl (this, "http", addr, backlog);
    }
.............................................
}

该对象又是ServerImpl对象的外观类,提供了HttpServer的方法,封装了ServerImpl自身的各种方法实现

 

最终在应用中调用this.httpserver.start()

本质上调用的就是sun.net.httpserver.ServerImpl对象的start()方法

 

---------------------------------------------------------------------------------------------------------------------------------------

下面分析下Dispatcher类中run方法的监听过程

public void run() {
//server的关闭标志,在调用httpserver.stop()方法后--->即ServerImpl类的stop()方法,设置finished为true(初始化为false) while (!finished) { try { /* process the events list first */ //由于支持HTTP1.1的原因,在一次发送数据结束之后,并不是立即关闭连接和socket,而是将发送完成作为一个事件传递过来,根据上下文决定是否关闭连接 while (resultSize() > 0) { Event r; synchronized (lolock) { r = events.remove(0); handleEvent (r); } } selector.select(1000); /* process the selected list now */ Set<SelectionKey> selected = selector.selectedKeys(); Iterator<SelectionKey> iter = selected.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); iter.remove (); if (key.equals (listenerKey)) { if (terminating) { continue; } SocketChannel chan = schan.accept(); if (chan == null) { continue; /* cancel something ? */ } chan.configureBlocking (false); SelectionKey newkey = chan.register (selector, SelectionKey.OP_READ); HttpConnection c = new HttpConnection (); c.selectionKey = newkey; c.setChannel (chan); newkey.attach (c); allConnections.add (c); } else { try { if (key.isReadable()) { boolean closed; SocketChannel chan = (SocketChannel)key.channel(); HttpConnection conn = (HttpConnection)key.attachment(); // interestOps will be restored at end of read key.interestOps (0); handle (chan, conn); } else { assert false; } } catch (IOException e) { HttpConnection conn = (HttpConnection)key.attachment(); logger.log ( Level.FINER, "Dispatcher (2)", e ); conn.close(); } } } } catch (CancelledKeyException e) { logger.log (Level.FINER, "Dispatcher (3)", e); } catch (IOException e) { logger.log (Level.FINER, "Dispatcher (4)", e); } catch (Exception e) { logger.log (Level.FINER, "Dispatcher (7)", e); } } }

  

 

Java实现Http服务器(四)

标签:

原文地址:http://www.cnblogs.com/wuxinliulei/p/4992633.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!