Tomcat源码解析(二):Connector

Connector的作用是什么?它主要实现了什么功能?

tomcat中Catalina包括Connector和Container,Connector主要功能是接收请求、将请求交给container进行处理。下面看一下Connector的主要功能。

一、Connector功能

初始化

调用open方法,创建socket。

private ServerSocket open()
    throws IOException, KeyStoreException, NoSuchAlgorithmException,
           CertificateException, UnrecoverableKeyException,
           KeyManagementException
    {

        // Acquire the server socket factory for this Connector
        ServerSocketFactory factory = getFactory();

        // If no address is specified, open a connection on all addresses
        if (address == null) {
            // "HttpConnector Opening server socket on all host IP addresses"
            log(sm.getString("httpConnector.allAddresses"));
            try {
                return (factory.createSocket(port, acceptCount));
            } catch (BindException be) {
                throw new BindException(be.getMessage() + ":" + port);
            }
        }

        // Open a server socket on the specified address
        try {
            InetAddress is = InetAddress.getByName(address);
            log(sm.getString("httpConnector.anAddress", address));
            try {
                return (factory.createSocket(port, acceptCount, is));
            } catch (BindException be) {
                throw new BindException(be.getMessage() + ":" + address +
                                        ":" + port);
            }
        } catch (Exception e) {
            log(sm.getString("httpConnector.noAddress", address));
            try {
                return (factory.createSocket(port, acceptCount));
            } catch (BindException be) {
                throw new BindException(be.getMessage() + ":" + port);
            }
        }

    }
run()方法

主要操作是:
获取socket

socket = serverSocket.accept(); 

创建processor,将socket交给processor处理。

// Hand this socket off to an appropriate processor
//如果得到processor为null,直接关闭该连接,忽略该请求
//用一个堆栈保存所有的processor,每次需要时,从堆栈中取最顶端的processor。且控制堆栈的大小在一定范围内。
HttpProcessor processor = createProcessor();
if (processor == null) {
    try {
        log(sm.getString("httpConnector.noProcessor"));
        socket.close();
    } catch (IOException e) {
        ;
    }
    continue;
}
//            if (debug >= 3)
//                log("run: Assigning socket to processor " + processor);
processor.assign(socket);

// The processor will recycle itself when it finishes

}

获取一个processor。用Stack processors保存所有的processor。

private HttpProcessor createProcessor() {

    synchronized (processors) {
        if (processors.size() > 0) {
            // if (debug >= 2)
            // log("createProcessor: Reusing existing processor");
            return ((HttpProcessor) processors.pop());
        }
        if ((maxProcessors > 0) && (curProcessors < maxProcessors)) {
            // if (debug >= 2)
            // log("createProcessor: Creating new processor");
            return (newProcessor());
        } else {
            if (maxProcessors < 0) {
                // if (debug >= 2)
                // log("createProcessor: Creating new processor");
                return (newProcessor());
            } else {
                // if (debug >= 2)
                // log("createProcessor: Cannot create new processor");
                return (null);
            }
        }
    }

}

二、processor的功能

run()方法,获取socket,并处理。

public void run() {

    // Process requests until we receive a shutdown signal
    while (!stopped) {

        // Wait for the next socket to be assigned
        Socket socket = await();
        if (socket == null)
            continue;

        // Process the request from this socket
        try {
            process(socket);
        } catch (Throwable t) {
            log("process.invoke", t);
        }

        // Finish up this request
        connector.recycle(this);

    }

    // Tell threadStop() we have shut ourselves down successfully
    synchronized (threadSync) {
        threadSync.notifyAll();
    }

}

run()调用process(),process()主要逻辑是,由socket获取input,创建request(获取sessionid等)和response,调用connector的container.invoke()方法,将request和response交给container来处理。

boolean ok = true;
boolean finishResponse = true;
SocketInputStream input = null;
OutputStream output = null;

// Construct and initialize the objects we will need
try {
    input = new SocketInputStream(socket.getInputStream(),
                                  connector.getBufferSize());
} catch (Exception e) {
    log("process.create", e);
    ok = false;
}

keepAlive = true;

while (!stopped && ok && keepAlive) {

    finishResponse = true;

    try {
        request.setStream(input);
        request.setResponse(response);
        output = socket.getOutputStream();
        response.setStream(output);
        response.setRequest(request);
        ((HttpServletResponse) response.getResponse()).setHeader
            ("Server", SERVER_INFO);
    } catch (Exception e) {
        log("process.create", e);
        ok = false;
    }


    // Parse the incoming request
    try {
        if (ok) {

            parseConnection(socket);
            parseRequest(input, output);
            if (!request.getRequest().getProtocol()
                .startsWith("HTTP/0"))
                parseHeaders(input);
            if (http11) {
                // Sending a request acknowledge back to the client if
                // requested.
                ackRequest(output);
                // If the protocol is HTTP/1.1, chunking is allowed.
                if (connector.isChunkingAllowed())
                    response.setAllowChunking(true);
            }

        }
    } catch (EOFException e) {
        // It's very likely to be a socket disconnect on either the
        // client or the server
        ok = false;
        finishResponse = false;
    } catch (ServletException e) {
        ok = false;
        try {
            ((HttpServletResponse) response.getResponse())
                .sendError(HttpServletResponse.SC_BAD_REQUEST);
        } catch (Exception f) {
            ;
        }
    } catch (InterruptedIOException e) {
        if (debug > 1) {
            try {
                log("process.parse", e);
                ((HttpServletResponse) response.getResponse())
                    .sendError(HttpServletResponse.SC_BAD_REQUEST);
            } catch (Exception f) {
                ;
            }
        }
        ok = false;
    } catch (Exception e) {
        try {
            log("process.parse", e);
            ((HttpServletResponse) response.getResponse()).sendError
                (HttpServletResponse.SC_BAD_REQUEST);
        } catch (Exception f) {
            ;
        }
        ok = false;
    }

    // Ask our Container to process this request
    try {
        ((HttpServletResponse) response).setHeader
            ("Date", FastHttpDateFormat.getCurrentDate());
        if (ok) {
            connector.getContainer().invoke(request, response);
        }
    } catch (ServletException e) {
    ...
    }
    ...
}

connector创建processor后,调用其await()方法,通知其处理某个socket。

synchronized void assign(Socket socket) {

    // Wait for the Processor to get the previous Socket
    //利用available变量通知processor它被调用了
    while (available) {
        //当前processor正在处理前一个socket中,所以要等待
        try {
            wait();
        } catch (InterruptedException e) {
        }
    }

    // Store the newly available Socket and notify our thread
    this.socket = socket;
    available = true;
    notifyAll();//

    if ((debug >= 1) && (socket != null))
        log(" An incoming request is being assigned");

}

三、总结

Connector处理请求的主要流程是:

1.connector获取socket,通过一个堆栈stack创建processor,通过processor.await(socket)交给processor

2.processor被创建时,就调用了processor.start()方法,所以如run()中所示,processor创建后就一直检查available变量(标识processor有没有被调用),并获取socket,然后进行处理。processor的处理,就是获取socket后,得到input等,创建request和response,传给connector.container进行处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值