tomcat NIO处理报文 是否需要拆包 粘包

tomcat NIO处理报文 是否需要拆包 粘包

文章目录

  • tomcat NIO处理报文 是否需要拆包 粘包
    • 首先有一点 默认的NIO `boolean keptAlive = false;`
    • 消息头长度
    • 方法是:org.apache.coyote.http11.Http11Processor.service
    • parseRequestLine(读取所有请求头)
    • 对于HTTP 消息体
    • 得到一般结论,普通的HTTP请求拆包的解决就是,对于头消息,读8K,然后获取content-length,对于chunk数据就使用分隔符
    • tomcat keep-alive的实现

看了很多文章,有的说用有的说不用,还是看一下tomcat是如何解决的把。

首先有一点 默认的NIO boolean keptAlive = false;

普通HTTP请求粘包绝无可能,都是短链接(不包括upgrade (websocket协议之类)),accept 只获取一个连接,断开就结束。

消息头长度

tomcat对HTTP header的长度是有限制的 protocol.getMaxHttpHeaderSize() == 8192也就是8kb

方法是:org.apache.coyote.http11.Http11Processor.service

parseRequestLine(读取所有请求头)

NioEndPoint

// 会调用`NioEndpoint:fillReadBuffer`方法,填满8k 
// 一次报文全部读完,如果超出就会发生异常,是异常
private int fillReadBuffer(boolean block, ByteBuffer to) throws IOException {
            int nRead;
            NioChannel channel = getSocket();
            if (block) { // 注意 这里是false
                // 省略
            } else {
                nRead = channel.read(to); // 一次读完清清楚楚
                if (nRead == -1) {
                    throw new EOFException();
                }
            }
            return nRead;
        }

对于HTTP 消息体

// 正如往常的解决方法一样,如果是
long contentLength = request.getContentLengthLong();
        if (contentLength >= 0) {
            if (contentDelimitation) { // 方法在preopareRequest的时候会被设置为false
                // contentDelimitation being true at this point indicates that
                // chunked encoding is being used but chunked encoding should
                // not be used with a content length. RFC 2616, section 4.4,
                // bullet 3 states Content-Length must be ignored in this case -
                // so remove it.
                headers.removeHeader("content-length");
                request.setContentLength(-1);
            } else {
                inputBuffer.addActiveFilter(inputFilters[Constants.IDENTITY_FILTER]);// 保证了httpservletRequerst能通过inpustream来获取请求体消息
                contentDelimitation = true;
            }
        }

得到一般结论,普通的HTTP请求拆包的解决就是,对于头消息,读8K,然后获取content-length,对于chunk数据就使用分隔符

tomcat keep-alive的实现

else if (state == SocketState.OPEN) {
                    // In keep-alive but between requests. OK to recycle
                    // processor. Continue to poll for the next request.
                    connections.remove(socket);
                    release(processor);
                    wrapper.registerReadInterest(); // 重新注册读事件
                    }

keep-alive的实现就是再次注册读事件!

你可能感兴趣的:(中间件)