getprivateprofilestring读不到数据_Tomcat NIO(11)请求数据读取
对于 tomcat 请求数据的读取来说,可以分为请求行的读取,请求头的读取,请求体的读取,三个部分方法调用序列图如下:
读取请求行
读取请求头
读取请求体
综合上面三个序列图,对于请求行,请求头,请求体的读取都最终调用了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 中的响应数据的写入。
getprivateprofilestring读不到数据_Tomcat NIO(11)请求数据读取相关推荐
- PostgreSQL 10.1 手册_部分 II. SQL 语言_第 5 章 数据定义_5.11. 外部数据
5.11. 外部数据 PostgreSQL实现了部分的SQL/MED规定,允许我们使用普通SQL查询来访问位于PostgreSQL之外的数据.这种数据被称为外部数据(注意这种用法不要和外键混淆,后者是 ...
- java删除页面数据不刷新_Ajax请求数据与删除数据后刷新页面
1.ajax异步请求数据后填入模态框 请求数据的按钮(HTML) ajax异步请求数据后给id为queryInfo的模态框赋值并弹出模态框(JS) //查询单个 functionquery(id) { ...
- R包自带数据汇总(自带数据包:datasets)
更新中 ... ... 引言 1.原子向量 + 条形图(一维) 1.1 欧元货币换算率 1.2 美国城市年降水量 1.3 北美主要河流的长度(不含河流名字) 1.4美国50个州信息(缩写.名称.全称) ...
- MongoDB 数据操作(二)数据查询(10)正则运算
来源:我的博客站 OceanicKang |<MongoDB 数据操作(二)数据查询(10)正则运算> 上一篇:<MongoDB 数据操作(二)数据查询(9)条件过滤> 如果要 ...
- Angular中使用HttpClientModule模块实现get请求数据和post提交数据
场景 Angular介绍.安装Angular Cli.创建Angular项目入门教程: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/detail ...
- 怎么调用获取被创建的预制体_Go 语言 Web 编程系列—— 获取用户请求数据(上)...
0.GET/POST 请求数据 在 PHP 中,可以直接通过全局变量 $_GET 和 $_POST 快速获取 GET/POST 请求数据,GET 请求数据主要是 URL 查询字符串中包含的参数,以前面 ...
- 通过Ajax异步请求数据
通过XMLHttpRequest对象的send()方法实现 <!DOCTYPE html> <html lang="en"> <head>< ...
- vue三种ajax请求方式,vue请求数据的三种方式
请求数据的方式: vue-resource 官方提供的 vue的一个插件 axios fetch-jsonp 一,vue-resource请求数据 介绍:vue-resource请求数据方式是官方提供 ...
- vue中使用axios请求数据过程
使用axios请求数据过程 1. 导入axios包 import axios from 'axios' 2. 在钩子函数中调用函数 mounted() {this.getinitialdata() / ...
最新文章
- 【安全加密技术】 对称加密
- 【BZOJ】3173: [Tjoi2013]最长上升子序列(树状数组)
- java二期_Java架构师鲁班二期
- 应用计算机测定线性电阻伏安特性实验器材,线性电阻与非线性电阻伏安特性实验的Origin处理...
- 安卓手机能用signal吗_现在的安卓手机可以直接更新成鸿蒙系统吗?还是必须购买新的手机?...
- P4513 小白逛公园 (线段树)
- 听说”双11”是这么解决线上bug的
- python中的[-1]、[:-1]、[::-1]、[n::-1]
- springboot 静态资源访问
- 【挖坑系列】关于浏览器の缓存机制
- 【技术白皮书】第四章:信息抽取技术产业应用现状及案例(下)
- 淘宝店铺上传成人用品类宝贝的错误解决
- linux的第一个逻辑分区表示为 ?,/dev/sda5 在 Linux 中表示 答案:第一块SCIS 硬盘上的逻辑分区...
- 修改elemntui tabs 下划线长短
- MBR10200FAC-ASEMI塑封肖特基二极管MBR10200FAC
- (ง •_•)ง[Python3 OpenCV4]10.平滑图像
- 南大庄建军计算机学院讲座,南京大学庄建军来校进行双创教育交流
- Result「?」 返回类型拼接
- 大鱼吃小鱼游戏代码 基于java-swing
- 一条视频涨粉10万+,情侣账号如何实现流量、变现两不误?
热门文章
- 弹跳机器人 桌游_MIT机器人轻松搞定桌游叠叠乐:你能玩过它算我输 |《科学》子刊...
- pyspark sparksession_PySpark 处理数据和数据建模
- opencv获得图片的像素宽度_使用OpenCV实现摄像头测距
- 黑苹果 选择语言 点不了_什么是天然的“黑钻”?—科普贴
- ANSIBLE--handlers的概念
- bash shell是如何识别特殊符号的
- SSH软件包:Sftp,scp和ssh-agent
- 教你在Ubuntu上体验Mac风格
- 关于liaoxuefeng的python3教程实战第四天
- activiti7流程设计器_变频空调器通信电路