Tomcat内核之ASCII解码的表驱动模式
我们知道Tomcat通信是建立在Socket的基础上,而套接字在服务器端和客户端传递的报文都是未经过编码的字节流,每8位组成1个字节,计算机以二进制为基础,这是由于使用晶体管的开合状态表示1和0,这样8个电晶体管就可以组成一个字节,这正是应用层使用的最小单位——字节。
在通过Socket进行网络通信的程序中,假如我们在接收到报文时不知道通过什么编码才能正确解码,最好的办法就是用Socket最底层的输入装置读取字节流,在确认编码后再对这些字节流进行转码,否则产生解码错误。我们常见的编码有ASCII、GB2312、UNICODE、UTF-8等等,除此之外还有很多其他编码,为什么会有这么多不同的编码?
ASCII编码即个字符已经完全满足使用英语的美国人,英语单词可以通过拆分成字母后用ASCII码表示。
则表示ASCII,如果两个大于127的字节连在一起则表示汉字,而且两个字节的值都在一定的范围内。经过一轮扩展后已经基本解决汉字编码不足问题。
再后来很多国家都按自己规定给自己的文字编码,对其他国家的编码一概不认识,情况一度混乱。接着国际标准化组织推出UNICODE编码,它要把全世界所有文字符号都包括进来,使用两个字节16位对所有字符进行编码,同时为了保证兼容ASCII码,低七位仍用于表示ASCII码原来的字符。通过UNICODE确实是把世界所有字符都统一起来了。
UNICODE编码虽然统一了所有字符,但还存在一个问题,如果是英文字符其实用一个字节已经足够,但使用UNICODE却必须要搭上另外一个毫无意义的字节,在网络传输过程中则意味着要多传输一倍无用的报文。于是引入UTF-8编码,它属于UNICODE的一种实现,它是一种变长的编码方式,在UTF-8规定的实现下可以用一个字节表示ASCII码表示的所有字符,避免了多余的空间浪费。
出了上面几种常见的编码,还有很多其他编码,不同编码指定的规则也不同,但基本都对ASCII做了兼容处理,可以说ASCII是最基础的,这节正是讨论ASCII码解密的常用方法——表驱动模式。
谈到web容器其实就是基于HTTP协议通信建立起两端通信,通过socket实现报文传输,传输过程肯定设计编码的约定,如果没有一个约定将导致消息解码错误。HTTP报文包括三部分:请求行、请求头和请求体(详细可参加前面HTTP协议章节),HTTP协议约定请求行和请求头必须用ASCII编码,这样才能把所有基于HTTP协议通信服务器统一起来,以免造成不同系统默认编码带来混乱。Tomcat接收到ASCII编码的报文,因为ASCII码长度为1字节(8位),java的byte长度也是1字节,两者刚好符合,所以在java中套接字接收到的报文是使用字节类型的数组进行缓冲存储。一般而言,我们比较关心ASCII码向数字、字母及几个特殊符号的解码,通过他们已经足以组成常用的词语语句。如下表,ASCII码中48-57分别表示数字0-9,65-90分别代表A-Z,97-122分别代表a-z。
在解码的过程涉及一些逻辑处理,例如解码后是否为英语字母、是大写还是小写、是否为数字、是否为空白符、转换为其他类型、大小写转换等等。我们惯用的办法是直接用if-else进行判断,如要判断一个ASCII编码是否为英语字母就判断编码是否在65到90、97到122之间,而表驱动思想则不是这样做,它把一张是否为英语字母的结果表放在内存,如下图所示,数组中标为t的表示是英语字母,数组的值即是结果。
类似地,根据其他需求可以在内存中存放更多张表,把判断的逻辑结果事先算好,直接获取数组值便是需要的结果。表驱动模式经常被用于取代很多if-else、switch-case逻辑判断语句中,它的使用有利于提高代码的可读性和维护性。Tomcat使用的ASCII表驱动类为org.apache.tomcat.util.buf.Ascii.java。
喜欢研究java的同学可以交个朋友,下面是本人的微信号:
Tomcat内核之ASCII解码的表驱动模式的更多相关文章
- (原创)c++11改进我们的模式之改进表驱动模式
所谓表驱动法(Table-Driven Approach),简单讲是指用查表的方法获取值.表驱动是将一些通过较为复杂逻辑语句来得到数据信息的方式,通过查询表的方式来实现,将数据信息存放在表里.对于消除 ...
- [lua]原来这才是表驱动的正确表达方式
曾经写了个很煞笔的脚本模拟switch..case语法形式.[lua]尝试一种Case语法糖 而今实际项目应用中突发,原来这才是正确的表驱动方式表达.如下所贴: function event_do( ...
- 查询优化--小表驱动大表(In,Exists区别)
Mysql 系列文章主页 =============== 本文将以真实例子来讲解小表驱动大表(In,Exists区别) 1 准备数据 1.1 创建表.函数.存储过程 参照 这篇(调用函数和存储过程批 ...
- 6.2 小表驱动大表(exists的应用)
1. 优化原则:小表驱动大表,即小数据集驱动大数据集. select * from A where id in (select id from B) 等价于: for select id from B ...
- MySQL高级知识(十六)——小表驱动大表
前言:本来小表驱动大表的知识应该在前面就讲解的,但是由于之前并没有学习数据批量插入,因此将其放在这里.在查询的优化中永远小表驱动大表. 1.为什么要小表驱动大表呢 类似循环嵌套 for(int i=5 ...
- 表驱动方法(Table-Driven Methods)
表驱动方法(Table-Driven Methods) - winner_0715 - 博客园 https://www.cnblogs.com/winner-0715/p/9382048.html W ...
- 了解MySQL联表查询中的驱动表,优化查询,以小表驱动大表
一.为什么要用小表驱动大表 1.驱动表的定义 当进行多表连接查询时, [驱动表] 的定义为: 1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表] 2)未指定联接条件时,行数少的表为[驱动表 ...
- Table-Driven Design 表驱动设计
注:本文所有代码来自 http://www.codeproject.com/Articles/42732/Table-driven-Approach 在许多程序中,经常需要处理那些拥有种种色色不同特性 ...
- Mysql优化原则_小表驱动大表IN和EXISTS的合理利用
//假设一个for循环 ; $i < ; $i++) { ; $i < ; $j++) { } } ; $i < ; $i++) { ; $i < ; $j++) { } } ...
随机推荐
- NOIP 2013
Prob.1 转圈游戏 找到循环节,然后快速幂.代码: #include<cstdio> #include<cstring> #include<iostream> ...
- hdu 5464(dp)
题意: 给你n个数,要求选一些数(可以不选),把它们加起来,使得和恰好是p的倍数(0也是p的倍数),求方案数. - - 心好痛,又没想到动规 #include <stdio.h> #inc ...
- bzoj3894
转载自http://www.cnblogs.com/rausen 3894: 文理分科 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1338 So ...
- xml 制作 RSS 订阅源
首先制作一个 RSS 模板,模板的文件名是 feed.xml,代码如下: <?xml version="1.0" encoding="utf-8"?> ...
- 华科机考:N阶楼梯上楼
时间限制:1秒空间限制:32768K 题目描述 N阶楼梯上楼问题:一次可以走两阶或一阶,问有多少种上楼方式.(要求采用非递归) 输入描述: 输入包括一个整数N,(1<=N<90). 输出描 ...
- Redis实现单点登录
http://blog.csdn.net/WuCourage/article/details/77802812
- 微信小程序开发 导入文件说没找到.json的问题
这个真的坑爹 网上的答案也没几个靠谱 说白了就是找个空文件直接创建 然后复制粘贴 反应了这玩意ide不成熟 进去之后直接创了个quick start的源码 也就是我们看的这个网页建议我们下载的源码 老 ...
- Linux下安装java的jdk和配置环境变量
每次感觉配这个超级简单 但是每次都要查下 记一下好了 Linux下安装jdk,步骤如下 1:下载jdk包:本章使用的为后缀为tar.gz的文件(不需要安装),如jdk-8u111-linux-x64. ...
- 03 持续集成和部署/基础设施 - DevOps之路
02 持续集成和部署/基础设施 - DevOps之路 文章Github地址,欢迎start:https://github.com/li-keli/DevOps-WiKi 服务的持续集成和部署这里有两套 ...
- SQL Server AlwaysON从入门到进阶(2)——存储
本文属于SQL Server AlwaysON从入门到进阶系列文章 前言: 本节讲解关于SQL Server 存储方面的内容,相对于其他小节而言这节比较短.本节会提供一些关于使用群集或者非群集系统过程 ...