Tomcat-客户端建立连接和发送请求的执行流程

本文详细阐述了Tomcat中客户端如何通过socket与服务端建立连接并发送请求的过程,包括服务端的NioEndpoint如何启动监听,Acceptor线程接收连接,Poller线程处理请求,以及Executor线程池执行客户端请求逻辑。同时,介绍了客户端请求从Connector的Http11NioProtocol开始,经过适配器、容器到Servlet的处理路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Tomcat组件在这里插入图片描述

这篇文章介绍的是客户端请求的接收过程,而不是tomcat的启动过程。关注点在:服务端在serverSocket启动、监听和客户端socket发送请求的执行过程。鉴于服务端通常是NIO模型,后面基于Http11NioProtocol协议介绍的。

服务端serverSocket启动和客户端socket请求监听的过程在这里插入图片描述

  • 在Connector组件init初始化的时,通过NioEndpoint的bind方法来绑定服务端端口。在Connector组件start启动的时,通过NioEndpoint的startInternal方法初始化线程池Executor、启动Poller线程和启动Acceptor线程。
  • Acceptor线程一直循环监听serverSocketChannel是否有连接,如果有连接,则accept接收客户端的链接socket,并向poller中的events队列增加OP_REGISTER事件。
//Acdeptor线程的主体逻辑
while (!stopCalled) {
   
     //accept客户端的请求socket
    socket = endpoint.serverSocketAccept();
    
    //向poller中的envets队列中添加OP_REGISTER事件
    endpoint.setSocketOptions(socket)
}

//accept客户端的链接socket
protected SocketChannel serverSocketAccept(){
   
   SocketChannel result = serverSock.accept();
   return result;
}

//向poller中的envets队列添加OP_REGISTER事件
protected boolean setSocketOptions(SocketChannel socket) {
   
    NioSocketWrapper socketWrapper = null;
    try {
   
        // Allocate channel and wrapper
        NioChannel channel = null;
        if (nioChannels != null) {
   
            channel = nioChannels.pop();
          }
        if (channel == null) {
   
           SocketBufferHandler bufhandler = new SocketBufferHandler(
                    socketProperties.getAppReadBufSize(),
                    socketProperties.getAppWriteBufSize(),
                    socketProperties.getDirectBuffer());
          if (isSSLEnabled()) {
   
                channel = new SecureNioChannel(bufhandler, this);
            } else {
   
                channel = new NioChannel(bufhandler);
             }
        }         
        NioSocketWrapper newWrapper = new NioSocketWrapper(channel, this);
        channel.reset(socket, newWrapper);
        connections.put(socket, newWrapper);
        socketWrapper = newWrapper;

        // Set socket properties
        // Disable blocking, polling will be used
        socket.configureBlocking(false);
        socketProperties.setProperties(socket.socket());

        socketWrapper.setReadTimeout(getConnectionTimeout());
        socketWrapper.setWriteTimeout(getConnectionTimeout());
        socketWrapper.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
        //向poller中的envets队列中添加OP_REGISTER事件
        poller.register(socketWrapper);
        return true;
    } catch (Throwable t) {
   
           //...
    }
    return false;
}
  • Poller线程处理events中的OP_REGISTER注册事件,在对应Selector中注册客户端socket的OP_READ兴趣事件,并且在循环中监听Selector中客户端socket中的事件,如果有请求事件发生,则调用方法processKey处理客户端socket的请求。
//Poller线程中的主要逻辑:
//1、处理Acceptor线程向events队列中添加的注册事件-events()方法处理;
//2、处理selector中客户端socket请求的事件-processKey(sk,socketWrapper)
public void run() {
   
            // Loop until destroy() is called
            while (true) {
   

                boolean hasEvents = false;

                try {
   
                    if (!close) {
   
                        
                       //处理Acceptor线程向events队列中添加的注册事件
                        hasEvents = events();
                        if (wakeupCounter.getAndSet(-1) > 0) {
   
                            // If we are here, means we have other stuff to do
                            // Do a non blocking select
                            keyCount = selector.selectNow();
                        } else {
   
                            keyCount = selector.select(selectorTimeout);
                        }
                        wakeupCounter.set(0);
                    }
                     
                    //没有请求读写事件发生,优先处理events队列中的注册事件
                    if (keyCount == 0) {
   
                        hasEvents = (hasEvents | events());
                    }
                } catch (Throwable x) {
   
                    ExceptionUtils.handleThrowable(x)<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值