Java 15 http 源码解析 之 ServerImpl

ServerImpl是http、https服务的实现。

下表为ServerImpl的成员

属性名 属性类型 笔者的理解
protocol String 协议
https boolean ??
executor Executor ??
httpsConfig HttpsConfigurator
sslContext SSLContext
contexts ContextList
address InetSocketAddress
schan ServerSocketChannel 用于管理socket,将在构造函数中绑定Ip地址
selector Selector
listenerKey SelectionKey
idleConnections Set<HttpConnection> 在构造函数中会获得一个线程安全的hashset, idleConnections = Collections.synchronizedSet (new HashSet<HttpConnection>())
allConnections Set<HttpConnection>
reqConnections Set<HttpConnection>
rspConnections Set<HttpConnection>
events List<Event>
lolock Object = new Object()
finished volatile boolean = false 当terminating且exchanges == 0被设置为true
terminating volatile boolean = false 在stop方法中设置为true
bound boolean = false
started private boolean = false 启动标志位
time volatile long
subticks volatile long = 0
ticks volatile long
wrapper HttpServer
CLOCK_TICK final static int = ServerConfig.getClockTick()
IDLE_INTERVAL final static long = ServerConfig.getIdleInterval()
MAX_IDLE_CONNECTIONS final static int = ServerConfig.getMaxIdleConnections()
TIMER_MILLIS final static long = ServerConfig.getTimerMillis ()
MAX_REQ_TIME final static long =getTimeMillis(ServerConfig.getMaxReqTime())
MAX_RSP_TIME final static long =getTimeMillis(ServerConfig.getMaxRspTime())
timer1Enabled final static boolean = MAX_REQ_TIME != -1
timer Timer
timer1 Timer1
logger final Logger 日志管理器
dispatcherThread Thread
dispatcher Dispatcher

部分成员函数

bind (InetSocketAddress addr, int backlog) : 绑定ip地址和backlog

public void bind (InetSocketAddress addr, int backlog) throws IOException {
    if (bound) {
        throw new BindException ("HttpServer already bound");
    }
    if (addr == null) {
        throw new NullPointerException ("null address");
    }
    ServerSocket socket = schan.socket();
    socket.bind (addr, backlog);
    bound = true;
}

setExecutor (Executor executor):设置Executor, 必须在server没有启动的时候设置。

DefaultExecutor会直接执行run(), 这种情况下是没有启动新的线程的。

public void setExecutor (Executor executor) {
    if (started) {
        throw new IllegalStateException ("server already started");
    }
    this.executor = executor;
}
private static class DefaultExecutor implements Executor {
    public void execute (Runnable task) {
        task.run();
    }
}
public Executor getExecutor () {
    return executor;
}

start() : 启动一个dispatcher线程,将started设置为true

public void start () {
    if (!bound || started || finished) {
        throw new IllegalStateException ("server in wrong state");
    }
    if (executor == null) {
        executor = new DefaultExecutor();
    }
    dispatcherThread = new Thread(null, dispatcher, "HTTP-Dispatcher", 0, false);
    started = true;
    dispatcherThread.start();
}

stop(): 唤醒selector处理事件; 关闭所有的HttpConnection(对于allConnections上锁); 取消定时器; 等待dispatcherThread结束。

public void stop (int delay) {
    if (delay < 0) {
        throw new IllegalArgumentException ("negative delay parameter");
    }
    terminating = true;
    try { schan.close(); } catch (IOException e) {}
    selector.wakeup();
    long latest = System.currentTimeMillis() + delay * 1000;
    while (System.currentTimeMillis() < latest) {
        delay();
        if (finished) {
            break;
        }
    }
    finished = true;
    selector.wakeup();
    synchronized (allConnections) {
        for (HttpConnection c : allConnections) {
            c.close();
        }
    }
    allConnections.clear();
    idleConnections.clear();
    timer.cancel();
    if (timer1Enabled) {
        timer1.cancel();
    }
    if (dispatcherThread != null && dispatcherThread != Thread.currentThread()) {
        try {
            dispatcherThread.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.log (Level.TRACE, "ServerImpl.stop: ", e);
        }
    }
}

createContext (String path, HttpHandler handler): 会根据路径和处理者去获得一个HttpContextImpl对象, 并且加入到ContextList类型的对象contexts中。该方法被synchronized修饰。

removeContext (String path), removeContext (HttpContext context): 从contexts中移除一个HttpContext类型的对象。该方法被synchronized修饰。

addEvent (Event r) :添加事件并且唤醒selector,利用lolock上锁。

void addEvent (Event r) {
    synchronized (lolock) {
        events.add (r);
        selector.wakeup();
    }
}

closeConnection(HttpConnection conn): 关闭连接,并且从连接池中移除