getprivateprofilestring读不到数据_Tomcat NIO(11)请求数据读取

在上一篇文章里我们主要介绍了 tomcat io 线程中涉及到的主要核心类,包括 AbstractProcessorLight,Http11Processor,CoyoteAdapter,这里主要介绍对于请求数据的读取。

对于 tomcat 请求数据的读取来说,可以分为请求行的读取,请求头的读取,请求体的读取,三个部分方法调用序列图如下:

读取请求行

618665fdc5ed296b42400c45ced644d4.png

读取请求头

6ab5820725ee8e34056bd8ab2d6a7e53.png

读取请求体

ae7a279dd51a6ca4b933cffab9dbedc3.png

综合上面三个序列图,对于请求行,请求头,请求体的读取都最终调用了NioSocketWrapper 对象实例的 fillReadBuffer() 方法。只不过请求行和请求头读取参数传递为 true,请求体读取参数传递为 false,该方法核心代码如下:

private int fillReadBuffer(boolean block, ByteBuffer to) throws IOException {    int nRead;    NioChannel socket = getSocket();    if (socket instanceof ClosedNioChannel) {        throw new ClosedChannelException();    }    if (block) {        Selector selector = null;        try {            selector = pool.get();        } catch (IOException x) {            // Ignore        }        try {            nRead = pool.read(to, socket, selector, getReadTimeout());        } finally {            if (selector != null) {                pool.put(selector);            }        }    } else {        nRead = socket.read(to);        if (nRead == -1) {            throw new EOFException();        }    }    return nRead;}
  • 根据上述方法分析,对于请求行和请求头的读取采用非阻塞的方式,用到了以前文章介绍的 NioChannel 对象的 read(ByteBuffer) 方法,其核心代码如下:
//NioChannelprotected SocketChannel scpublic int read(ByteBuffer dst) throws IOException {    return sc.read(dst); }
  • 根据上述代码,请求行和请求头的读取本质是调用 java NIO api SocketChannel 的 read() 方法,该方法为非阻塞方法。如果读不到数据就直接返回,继续由以前文章介绍的 poller 线程监测是否有数据可读。
  • 对于请求体的读取采用阻塞的方式,调用以前文章中介绍的 NioSelectorPool 的read(ByteBuffer buf, NioChannel socket, Selector selector, long readTimeout) 方法。在该方法中又会调用 NioBlockingSelector 的 read() 方法,核心代码如下:

    public int read(ByteBuffer buf, NioChannel socket, long readTimeout) throws IOException {    SelectionKey key = socket.getIOChannel().keyFor(socket.getSocketWrapper().getPoller().getSelector());    if (key == null) {        throw new IOException(sm.getString("nioBlockingSelector.keyNotRegistered"));    }    KeyReference reference = keyReferenceStack.pop();    if (reference == null) {        reference = new KeyReference();    }    NioSocketWrapper att = (NioSocketWrapper) key.attachment();    int read = 0;    boolean timedout = false;    int keycount = 1; //assume we can read    long time = System.currentTimeMillis(); //start the timeout timer    try {        while (!timedout) {            if (keycount > 0) { //only read if we were registered for a read                read = socket.read(buf);                if (read != 0) {                    break;                }            }            try {                if (att.getReadLatch()==null || att.getReadLatch().getCount()==0) {                    att.startReadLatch(1);                }                poller.add(att,SelectionKey.OP_READ, reference);                att.awaitReadLatch(AbstractEndpoint.toTimeout(readTimeout), TimeUnit.MILLISECONDS);            } catch (InterruptedException ignore) {                // Ignore            }            if ( att.getReadLatch()!=null && att.getReadLatch().getCount()> 0) {                //we got interrupted, but we haven't received notification from the poller.                keycount = 0;            }else {                //latch countdown has happened                keycount = 1;                att.resetReadLatch();            }            if (readTimeout >= 0 && (keycount == 0)) {                timedout = (System.currentTimeMillis() - time) >= readTimeout;            }        }        if (timedout) {            throw new SocketTimeoutException();        }    } finally {        poller.remove(att,SelectionKey.OP_READ);        if (timedout && reference.key != null) {            poller.cancelKey(reference.key);        }        reference.key = null;        keyReferenceStack.push(reference);    }    return read;}
  • 根据以上代码整个读数据逻辑在一个循环里进行,如果有数据读到就跳出循环,返回数据。
  • 如果没有数据,则调用 BlockPoller 的 add() 方法,该方法将封装的 OP_READ 事件添加到 BlockPoller 的事件队列里。关于 BlockPoller 我们在后面文章里详细讲解。
  • 然后在调用以前文章介绍的 NioSocketWrapper 中的 CountDownLatch 类型 readLatch 属性的 await() 方法,使当前线程(一般是tomcat io线程)在 readLatch 上等待。
  • 当前线程在 readLatch 上等待一般有超时时间(读超时时间),默认不配置为 -1,这时超时时间为 Long.MAX_VALUE 毫秒。

对于 tomcat 数据读取总结如下:

  • 对于请求行,请求头和请求体的读取默认(不开启异步)都在 tomcat io 线程中进行。

  • 对于请求行和请求头的读取是非阻塞读取,即不阻塞 tomcat io 线程,如果没有读取到数据,则由 poll 线程继续监测下次数据的到来。

  • 对于请求体的读取是阻塞的读取,如果发现请求体数据不可读,那么首先注册封装的 OP_READ 事件到 BlockPoller 对象实例的事件队列里。然后利用 NioSocketWrapper 对象中的 readLatch 来阻塞 tomcat io 线程。

  • 对于 tomcat io 线程阻塞时间为读超时,默认不配置为 -1,这时超时时间为 Long.MAX_VALUE 毫秒。

  • 如果超时,则抛出 SocketTimeoutException,并取消上面注册的读事件。

  • 最后将该事件从 selector 中移除(一般是可读事件)。

目前先写到这里,下一篇文章里我们继续介绍 tomcat 中的响应数据的写入。

d9656f760268cff530347c9e8a70f734.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543258.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OC之类方法

#import<Foundation/Foundation.h> /* 1、对象方法 &#xff08;1&#xff09;减号- 开头 &#xff08;2&#xff09;只能由对象来调用 &#xff08;3&#xff09;对象方法中能访问当前对象的成员变量&#xff08;实例变量&#xff09; 2、类方法 &#xff08;1&#xff…

mysql 主机不存在_MySQL 当记录不存在时插入,当记录存在时更新

MySQL 当记录不存在时插入&#xff0c;当记录存在时更新2012-1-30 17:58 Monday分类&#xff1a;MySQL评论(71) 浏览(21592)MySQL 当记录不存在时插入&#xff0c;当记录存在时更新网上基本有三种解决方法。第一种&#xff1a;示例一&#xff1a;插入多条记录假设有一个主键为 …

Autodesk招聘开发咨询顾问(北京或上海),需要内推的扔简历过来啊

Autodesk现招聘两位二次开发技术顾问&#xff0c;为正式编制。享受所有Autodesk优越的福利资源&#xff08;额外商业保险&#xff0c;公积金全部由公司支付&#xff0c;年度奖金&#xff0c;季度礼物, 节日礼物, 15天年假&#xff0c;不定期的培训...)。 Autodesk 是中国的最佳…

企业办公自动化系统_OA系统的核心功能有哪些?分析当下OA系统的缺陷以及相关解决方案...

什么是OA系统&#xff0c;OA是英语Office Automation的简称&#xff0c;字面意思是办公自动化&#xff0c;即将计算机、通信等现代化技术运用到传统办公中&#xff0c;进而形成的一种新型办公方式。它利用现代化设备和信息化技术&#xff0c;代替了办公人员传统的部分手动或重复…

python whl_python whl是什么文件

在安装whl文件之前&#xff0c;我们需要先搞清楚什么是whl文件&#xff0c;whl格式本质上是一个压缩包&#xff0c;里面包含了py文件&#xff0c;以及经过编译的pyd文件。使得可以在不具备编译环境的情况下&#xff0c;选择合适自己的python环境进行安装。在Win7下安装whl文件&…

android activity生命周期_Android岗高频面试题合一集,看你能答出几题?

前言面试季黄金时期来袭&#xff0c;想必许多朋友在这时有找工作、换工作、跳槽涨薪等想法&#xff0c;但你们都有一个相同的过程那就是面试。大家肯定想知道面试时都问哪些面试相关问题&#xff0c;所以就去网上查找题去刷题&#xff0c;为了省去大家找题的时间&#xff0c;小…

java web判断服务器是否是本机

1,如何获取浏览器的ip Java代码 /*** * 获取客户端ip地址(可以穿透代理) * param request * return */ public static String getClientIpAddr(HttpServletRequest request) { String ip request.getHeader("X-Forwarded-For"…

python变量分类_Python 入门系列 —— 5. 三大变量类型介绍

多值赋给多变量Python 允许在一行中将多个值赋给多个变量。x, y, z "Orange", "Banana", "Cherry"print(x)print(y)print(z)---- output ------PS E:\dream\markdown\python> & "C:/Program Files (x86)/Python/python.exe" e…

数据字典简单例子_Python学习100天-Day14(数据分析篇-pandas02)

Day14-读取文件接着上一天的内容&#xff0c;我在学习的过程中发现&#xff0c;DF数据还可以利用几个Series数据组成&#xff0c;具体看一个例子&#xff1a;两种形式&#xff0c;第一种是直接对Series创建DF对象&#xff0c;得出的结果。第二种是通过字典的形式创建DF对象&…

Java基础知识总结

一&#xff1a;java概述&#xff1a; 1991 年Sun公司的James Gosling&#xff08;詹姆斯&middot;高斯林&#xff09;等人开始开发名称为 Oak 的语言&#xff0c;希望用于控制嵌入在有线电视交换盒、PDA等的微处理器&#xff1b; 1994年将Oak语言更名为Java&#xff1b; Jav…

把百度网站设为首页_网站百度推广效果好不好?怎样才能把网站推广到百度首页?...

在移动互联网营销的过程中&#xff0c;有着各式各样的营销手段&#xff0c;也有着丰富多彩的营销平台&#xff0c;而百度平台是大家非常熟悉的&#xff0c;它拥有着亿万用户&#xff0c;几乎小伙伴们每天都需要通过百度查找各种资讯&#xff0c;来满足自己的需求&#xff0c;丰…

ZZULI 1876: 蛤玮的项链 Hash + 二分

Time Limit: 6 Sec Memory Limit: 128 MBSubmit: 153 Solved: 11SubmitStatusWeb BoardDescription 蛤玮向心仪的妹子送了一条项链,这条项链是由小写字母构成的首尾相接的字符串,妹子看了看项链对蛤玮说,"我希望它是对称的",蛤玮想了想之后决定,从项链上截取出一段…

python调用菜单响应事件_Python处理菜单消息操作示例【基于win32ui模块】

本文实例讲述了Python处理菜单消息操作。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 一、代码 # -*- coding:utf-8 -*- #! python3 import win32ui import win32api from win32con import * from pywin.mfc import window class MyWnd(window.Wnd): def __init__ (…

ucharts 折线 点_ucharts图表引入的两种方式

import uCharts from ../js_sdk/u-charts/u-charts/u-charts.js; //可以优化放全局 uCharts >使用全局const lineCharts {},optionAs {};export default {name: LineChart,props: {dataAs: {//数据type: Object,default: () > ({})},basicAs: {通用基础项设置type: Obj…

VMI和JIT

1&#xff0e;JIT生产方式的含义JIT生产方式的基本思想可用现在已经广为流传的一句话来概括&#xff0c;即“只在需要时&#xff0c;按需要的量&#xff0c;生产所需的产品”&#xff0c;这也就是just in time一词所要表达的本来含义。这种生产方式的核心是追求一种零库存、零浪…

全连接条件随机场_条件随机场CRF简介

作者&#xff1a;Ravish Chawla编译&#xff1a;ronghuaiyang导读一个简单明了的对条件随机场的说明&#xff0c;给大家一个非常直观的印象&#xff0c;CRF到底是个什么东西&#xff0c;能干什么用。条件随机场是一种用于序列预测的判别模型。它们使用来自以前标签的上下文信息…

java特殊字符转义字符_Java正则表达式处理特殊字符转义的方法

正则需要转义字符$, (, ), *, , ., [, ], ?, \\, ^, {, }, |异常现象&#xff1a;java.util.regex.PatternSyntaxException: Dangling meta. character * near index 0解决方法对特殊字符加\\转义即可。注意&#xff1a;虽然使用[]在部分条件下也可以&#xff0c;但是在对于(、…

PHP文件下载过滤类

Java代码 <?php /** $filename index.php; $download new Download(php,exe,html, false); if (!$download->downloadfile($filename)) { echo $download->getErrorMsgs(); } */ class Download { private $debug false; private $errorMsg ; …

excel支持python吗_没有 Python,微软宣布 Excel 新增 JavaScript 支持

CSDN”&#xff0c;选择“置顶公众号” 关键时刻&#xff0c;第一时间送达&#xff01; 去年年底曾有外媒报道&#xff0c;由于社区用户的强烈要求&#xff0c;谷歌正考虑添加 Python 作为官方的一种 Excel 脚本语言。 当时&#xff0c;谷歌开启了一个针对 Excel 功能的话题&am…

java 压缩gz_如何在Java中将.zip压缩为.gz?

我认为您可以为zip创建一个临时文件,将其添加到gzip,然后删除创建的zip.下面的代码示例应该可以帮助您.public void ZIPandGZIP(String fileName, OutputStream os, String header) throws FileNotFoundException {byte[] buffer new byte[1024];FileInputStream fis null;Fi…