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

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


看了很多文章,有的说用有的说不用,还是看一下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的实现就是再次注册读事件!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值