我们知道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解码的表驱动模式的更多相关文章

  1. (原创)c++11改进我们的模式之改进表驱动模式

    所谓表驱动法(Table-Driven Approach),简单讲是指用查表的方法获取值.表驱动是将一些通过较为复杂逻辑语句来得到数据信息的方式,通过查询表的方式来实现,将数据信息存放在表里.对于消除 ...

  2. [lua]原来这才是表驱动的正确表达方式

    曾经写了个很煞笔的脚本模拟switch..case语法形式.[lua]尝试一种Case语法糖 而今实际项目应用中突发,原来这才是正确的表驱动方式表达.如下所贴: function event_do( ...

  3. 查询优化--小表驱动大表(In,Exists区别)

    Mysql 系列文章主页 =============== 本文将以真实例子来讲解小表驱动大表(In,Exists区别) 1 准备数据 1.1 创建表.函数.存储过程 参照  这篇(调用函数和存储过程批 ...

  4. 6.2 小表驱动大表(exists的应用)

    1. 优化原则:小表驱动大表,即小数据集驱动大数据集. select * from A where id in (select id from B) 等价于: for select id from B ...

  5. MySQL高级知识(十六)——小表驱动大表

    前言:本来小表驱动大表的知识应该在前面就讲解的,但是由于之前并没有学习数据批量插入,因此将其放在这里.在查询的优化中永远小表驱动大表. 1.为什么要小表驱动大表呢 类似循环嵌套 for(int i=5 ...

  6. 表驱动方法(Table-Driven Methods)

    表驱动方法(Table-Driven Methods) - winner_0715 - 博客园 https://www.cnblogs.com/winner-0715/p/9382048.html W ...

  7. 了解MySQL联表查询中的驱动表,优化查询,以小表驱动大表

    一.为什么要用小表驱动大表 1.驱动表的定义 当进行多表连接查询时, [驱动表] 的定义为: 1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表] 2)未指定联接条件时,行数少的表为[驱动表 ...

  8. Table-Driven Design 表驱动设计

    注:本文所有代码来自 http://www.codeproject.com/Articles/42732/Table-driven-Approach 在许多程序中,经常需要处理那些拥有种种色色不同特性 ...

  9. Mysql优化原则_小表驱动大表IN和EXISTS的合理利用

    //假设一个for循环 ; $i < ; $i++) { ; $i < ; $j++) { } } ; $i < ; $i++) { ; $i < ; $j++) { } } ...

随机推荐

  1. ●hihocoder #1394 网络流四·最小路径覆盖

    题链: http://hihocoder.com/problemset/problem/1394 题解: 有向图最小路径覆盖:最少的路径条数不重不漏的覆盖所有点. 注意到在任意一个最小路径覆盖的方案下 ...

  2. SqlServer 跨网段跨服务器复制

    注意:被同步的表必须有主键,否则无法同步.对数据库进行操作时需要登录服务器,在服务器本地进行操作,远程对数据库进行操作不能完成所有的步骤 准备工作: 1.将发布数据库完整备份到订阅服务器上,并在订阅服 ...

  3. 数组中存放对象之java中定义类数组存放类

    public class ClassArrayDemo { int age; String name; ClassArrayDemo(int age, String name) { this.age ...

  4. SSH搭建spring,使用依赖注入的方法

    配置文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.o ...

  5. Lock锁子类了解一下

    前言 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 多线程基础必要知识点!看了学习多线程事半功倍 Java锁机制了解一下 AQS简简单单过一遍 只有光头才能变强! 上一篇已经将Loc ...

  6. Node.js DNS 模块

    Node.js DNS 模块用于解析域名.引入 DNS 模块语法格式如下: var dns = require("dns") 方法 序号 方法 & 描述 1 dns.loo ...

  7. jQuery 效果 – 隐藏和显示

    在 jQuery 中可以使用 hide() 和 show() 方法来隐藏和显示 HTML 元素,以及使用 toggle() 方法能够切换 hide() 和 show() 方法. 隐藏.显示.切换,滑动 ...

  8. shiro架构

    1 shiro介绍  1.1 什么是shiro 分享牛系列,分享牛专栏,分享牛.shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权.加密.会 ...

  9. PHP学习(3)—在HTML中嵌入PHP

    我们以一个提交订单和显示订单信息的例子为学习PHP的开始.这个例子包含两个文件.一个提交订单的html文件:orderform.html,一个显示订单信息的php文件:processorder.php ...

  10. MTK8127编译sdk出错解决方法

    1.按照源码中sdk目录下的howto_build_SDK.txt参考文档的编译方式  $ cd ~/my-android-git  $ . build/envsetup.sh  $ lunch sd ...