jinfo

jinfo jinfo可以输出并修改运行时的java 进程的opts。用处比较简单,用于输出JAVA系统参数及命令行参数。用法是jinfo -opt pid 如: 查看2788的MaxPerm大小可以用 jinfo -flag MaxPermSize 2788 jinfo -flag MaxHeapSize 13112 打印命令行标识参数和系统属性键值对。 -flag name 打印指定的命令行标识参数的名称和值。 -flag [+|-]name 启用或禁用指定的boolean类型的命令行标识参数。 -flag name=value 为给定的命令行标识参数设置指定的值。 -flags 成对打印传递给JVM的命令行标识参数。 -sysprops 以键值对形式打印Java系统属性。 -h 打印帮助信息。 -help 打印帮助信息。 http://www.softown.cn/post/182.html

2011-11-11 · 1 min · 34 words · -

interview index

Interview index https://www.techinterviewhandbook.org/best-practice-questions/ https://raymondjiang.net/2022/02/18/about-leetcode-blind-75/?utm_short=pu2Q5X https://leetcode-cn.com/circle/discuss/CTEQMT/ #http://www.wiloon.com/?p=4781 #http://www.wiloon.com/?p=4219 #http://www.wiloon.com/?p=4117 #http://www.wiloon.com/?p=19

2011-11-11 · 1 min · 9 words · -

数字单位, 十亿,百亿,兆

数字单位, 十亿,百亿,兆 个十百千万亿兆京垓秭穰沟 个十百千万,十万,百万,千万,亿,十亿,百亿,千亿,兆,十兆,百兆,千兆,万兆,亿兆,后面是京,京之后的单位有十京、百京、千京、垓、十垓、百垓、千垓、秭、十秭、百秭、千秭、穰、十穰、百穰、千穰、沟…

2011-11-09 · 1 min · 4 words · -

dentry

dentry 上一节提到了,struct file并不是文件系统的核心数据结构,那么dentry和inode,这两个结构体谁是文件系统的核心数据结构呢,它们存在的目的又分别是什么呢? 首先dentry是目录项缓存,是一个存放在内存里的缩略版的磁盘文件系统目录树结构,他是directory entry的缩写。我们知道文件系统内的文件可能非常庞大,目录树结构可能很深,该树状结构中,可能存在几千万,几亿的文件。 首先假设不存在dentry这个数据结构,我们看下我们可能会面临什么困境: 比如我要打开/usr/bin/vim 文件, 1 首先需要去/所在的inode找到/的数据块,从/的数据块中读取到usr这个条目的inode, 2 跳转到user 对应的inode,根据/usr inode 指向的数据块,读取到/usr 目录的内容,从中读取到bin这个条目的inode 3 跳转到/usr/bin/对应的inode,根据/usr/bin/指向的数据块,从中读取到/usr/bin/目录的内容,从里面找到vim的inode 我们都知道,Linux提供了page cache页高速缓存,很多文件的内容已经缓存在内存里,如果没有dentry,文件名无法快速地关联到inode,即使文件的内容已经缓存在页高速缓存,但是每一次不得不重复地从磁盘上找出来文件名到VFS inode的关联。 因此理想情况下,我们需要将文件系统所有文件名到VFS inode的关联都纪录下来,但是这么做并不现实,首先并不是所有磁盘文件的inode都会纪录在内存中,其次磁盘文件数字可能非常庞大,我们无法简单地建立这种关联,耗尽所有的内存也做不到将文件树结构照搬进内存 https://bean-li.github.io/vfs-inode-dentry/

2011-11-09 · 1 min · 24 words · -

关于 XML standalone 的解释

关于 XML standalone 的解释 http://www.blogjava.net/javafuns/articles/257525.html XML standalone 定义了外部定义的 DTD 文件的存在性. standalone element 有效值是 yes 和 no. 如下是一个例子: ……… 值 no 表示这个 XML 文档不是独立的而是依赖于外部所定义的一个 DTD. 值 yes 表示这个 XML 文档是自包含的(self-contained).

2011-11-08 · 1 min · 29 words · -

WS-I

WS-I WS-I是Web Services Interoperability Organization的缩写,意为网络服务协同组织。WS-I (Web Services Interoperability Organization) 于2002年2月6日由包括微软、IBM、SAP、ORACLE、Intel等在内的9家IT行业领袖和46家公司联合宣告成立。业界对于WS-I的关注首先在于对网络服务兼容性将带来的重要影响;另一方面,尽管该组织联合了众多竞争对手的参与,但是在网络服务技术方面作为微软公司最直接、最据威胁的竞争对手的SUN公司并未参与这项联盟。 WS-I提出了3个目标: (1) 为客户的网络服务应用提供实施指导和培训; (2) 促进跨平台、跨应用软件和跨程序语言的网络服务的一致和兼容,并保证可靠兼容; (3) 致力于使网络服务协同成为本行业共同遵守的准则,以帮助客户在网络服务技术的选择上轻松决策,提高网络服务的应用范围和水平,并确保网络服务技术的持续发展。 为实现上述目标,WS-I计划开展下面的工作: (1) 提供网络服务测试和实施指导 (测试网络服务是否符合标准来确保他们能够成功集成) ,以促进客户的网络服务应用; (2) 提供网络服务系统框架,支持和推动关键网络服务标准的使用; (3) 发布网络服务技术路标规划,帮助客户了解网络服务解决方案的长期发展方向。 WS-I为Web服务开发商提供了一系列资源,这些资源可以帮助他们创建可互操作的Web服务并验证他们的结果是否遵从WS-I的指导方针。WS-I的主要成果包括概要,应用样本和测试工具。 概要为相关Web服务更好的一起互操作的使用提供了实现的指导方针。直到今日,WS-I已经定稿的有Basic Profile,Attachments Profile和简单SOAP绑定Profile。Basic Security Profile还在指定当中。 应用样本演示了符合WS-I知道方针的Web服务应用。这些实现的开发运用了多种平台、语言和开发工具,并演示了互操作性,为Web服务开发厂商提供了可用的资源。应用样本作为应用的实例可以作为参考让开发商在他们自己特有的环境下遵循WS-I的指导方针。直至今日,WS-I已经为Basic Profile实现了11个应用样本。 测试工具是用来测试Web服务的消息交换是否遵循WS-I的指导方针。这些工具监控消息并分析结果来确定是哪些互操作问题。这些测试能力对开发商来说很重要,这样才能确保他们在运用Web服务规范下的实现遵从现在的互操作指导方针。测试是在自我管理下进行的,目的是为了发现规范实现中非传统的用法和错误,这样可以帮助改善应用和平台间的互操作性。直至今日,WS-I已经为开发商开发的测试工具可以核实与Basic Profile1.0的一致性,有关其他WS-I profile的测试工具的制定还在进行中。

2011-11-02 · 1 min · 37 words · -

控制协程(goroutine)的并发数量

控制协程(goroutine)的并发数量 ants https://github.com/panjf2000/ants/blob/master/README_ZH.md 利用 channel 的缓存区 可以利用信道 channel 的缓冲区大小来实现: // main_chan.go func main() { var wg sync.WaitGroup ch := make(chan struct{}, 3) for i := 0; i < 10; i++ { ch <- struct{}{} wg.Add(1) go func(i int) { defer wg.Done() log.Println(i) time.Sleep(time.Second) <-ch }(i) } wg.Wait() } https://geektutu.com/post/hpg-concurrency-control.html

2011-10-31 · 1 min · 49 words · -

技术大牛谈HTML 5设计原理

技术大牛谈HTML 5设计原理 http://developer.51cto.com/art/201103/247880.htm 2011-03-08 10:15 李松峰 李松峰博客 本篇文章是Jeremy Keith在 Fronteers 2010 上的主题演讲,主要跟大家谈谈HTML 5的设计。主要分两个方面,一方面就是HTML 5;另一方面就是80/20。 Jeremy Keith在 Fronteers 2010 上的主题演讲 下载PPT(PDF) http://adactio.com/extras/slides/designofhtml5.pdf 观看视频 http://fronteers.nl/congres/2010/sessions/the-design-of-html5-jeremy-keith 51CTO推荐专题: HTML 5 下一代Web开发标准详解 今天我想跟大家谈一谈HTML 5的设计。主要分两个方面: 一方面,当然了,就是HTML 5。我可以站在这儿只讲HTML 5,但我并不打算这样做,因为如果你想了解HTML 5的话,你可以Google,可以看书,甚至可以看规范。 实际上,确实有人会谈到规范的内容。史蒂夫·福克纳(Steve Faulkner)会讲HTML 5与可访问性。而保罗·艾里什(Paul Irish)则会讲HTML 5提供的各种API。因此,我今天站在这里,不会光讲一讲HTML 5就算完事了。 说老实话,在正式开始之前,我想先交待清楚我所说的HTML 5到底是什么意思。这话听起来有点搞笑: 这会子你一直在说HTML 5,难道我们还不知道什么是HTML 5吗?大家知道,有一个规范,它的名字叫HTML 5。我所说的HTML 5,指的就是这个规范。但问题是,有些人所说的HTML 5,指的不仅仅是这个规范,还有别的意思。比如说,用HTML 5来代指CSS3就是一种常见的叫法。我可不是这样的。我所说的HTML 5,不包含CSS3,就是HTML 5。 类似的术语问题以前也有过。Ajax本来是一种含义明确的技术,但过了不久,它的含义就变成了"用JavaScript来做一切好玩的东西"。这就是Ajax,对不对?今天,HTML 5也面临同样的问题,它本来指的是一个特定的规范,但如今含义却成了"在Web上做一切好玩的事。"我说的不是这种HTML 5,不是这种涵盖了最近刚刚出现的各种新东西的HTML 5。我说的仅仅是规范本身: HTML 5。 刚才已经说了,我今天想要讲的内容不多,也没有打算介绍HTML 5都包含什么。今天我要讲的是它的另一方面,即HTML 5的设计。换句话说,我要讲的不是规范里都包含什么,而是规范里为什么会包含它们,以及在设计这个规范的时候,设计者们是怎么看待这些东西的。 设计原理 设计原理本质上是一种信念、一种想法、一个概念,是你行动的支柱。不管你是制定规范,还是制造一种有形的物品,或者编写软件,甚至发明编程语言。你都能找到背后的一个或者多个设计原理,多人协作的任何成果都是例证。不仅仅Web开发领域是这样。纵观人类历史,像国家和社会这样大规模的构建活动背后,同样也有设计原理。 就拿美国为例吧,美国的设计原理都写在了《独立宣言》中了。 我们认为这些真理是不言而喻的,人人生而平等,造物主赋予了每个人不可剥夺的权利,包括生存、自由和追求幸福。 这里有一句口号: 生存、自由和追求幸福。这是被写进宪法中的核心理念,它关系到我们所有人的一切,也就是我们构建自己社会的原则。 还有一个例子,就是卡尔·马克思(Karl Marx),他的著作在20世纪曾被奉为建设社会主义的圭臬。其基本思想大致可以归结为下面这条设计原理: 各尽所能,各取所需。 这其实就是一种经济体系背后的设计原理。 还有一个例子,比前面两个的历史更久远一些,不过大同小异: 人人为我,我为人人。 这个极为简单的设计原理,是两千年前的拿撒勒犹太人耶稣基督提出来的。而这条原则成为了后来许多宗教的核心教义。原理与实践有时候并不是同步的。 下面是小说中的一个例子。英国小说家乔治·奥威尔(George Orwell)笔下的《动物庄园》,就是在一条设计原理的基础上构建起来的虚拟社会。这条设计原理是: 四条腿的都是好人,两条腿的都是坏蛋! 《动物庄园》中有意思的是,随着社会的变迁——变得越来越坏,这条设计原理也跟着发生了改变,变成了"四条腿的都是好人,两条腿的就更好了。"最关键的是,即使是在虚构的作品里,设计原理都是存在的。 还有一套虚构的作品是以三条设计原理为基础构建起来的,那就是美国著名小说家艾萨克·阿西莫夫(Issac Asimov)的机器人经典系列。阿西莫夫发明了机器人学这个术语,并提出了机器人学三大法则,然后在这三个简单的设计原理基础上创作了一系列经典作品——大约有50本书。无论作品的情节如何变化,实际上都是从不同的角度来阐释这三大设计原理。我想,在座各位对机器人三大法则都不应该陌生。 机器人不得伤害人类,或袖手旁观人类受伤害。 机器人必须服从人类命令,除非命令违反第一法则。 机器人必须自卫,只要不违背第一和第二法则。 这些恐怕是第一次出现在小说中的针对软件的设计原理了。虽然基于这三个设计原理的软件运行在虚构的机器人的"正电子脑"中,但我想这应该是软件设计原理的事实开端。从此以后,我们才看到大量优秀软件背后的设计原理。 蒂姆·伯纳斯-李(Tim Berners-Lee),Web的发明者,在W3C的网站上发表过一份文档,其中有一个URL给出了他自己的一套设计原理。这些设计原理并不那么容易理解,不仅多,而且随着时时间推移,他还会不断补充、修改和删除。不过我还是觉得把自己认同的设计原理写出来放在某个地方真是个不错的主意。 实际上,CSS的发明人之一伯特·波斯(Bert Bos),也在W3C的网站上放着一份文档,其中讲的都是基本的设计原理,比如怎样设计并构建一种格式,无论是CSS还是其他格式。推荐大家看一看。 只要你在W3C的站点中随便找一找,就可以发现非常多的这种设计原理,包括蒂姆·伯纳斯-李个人的。当然,你还会看到他从软件工程学校里借用的一些口号: 分权(decentalisation)、容忍(tolerance)、简易(simplicity)、模块化(modularity)。这些都是在他发明新格式的时候,头脑中无时无刻不在想的那些关键词。 在座各位对蒂姆·伯纳斯-李的贡献都是非常熟悉的,因为大家每天都在用。他发明了Web,与罗伯特·卡里奥(Robert Cailliau)共同发明了Web,而且在发明Web的同时,也发明了我们每天都在Web上使用的语言。当然,这门语言就是HTML: 超文本标记语言。 HTML HTML最早是从2.0版开始的。从来就没有1.0版。如果有人告诉你说,他最早是从HTML 1.0开始使用HTML的,那他绝对是在忽悠你。从前确实有一个名叫HTML Tags的文档,其中的部分标签一直用到现在,但那个文档并非官方的规范。 使用标签、尖括号、p或h1,等等,并不是蒂姆·伯纳斯-李首创的想法。当时的SGML里就有了这些概念,而且当时的CERN(Conseil Europeen pour la Recherche Nucleaire,欧洲核子研究委员会)也在使用SGML的一个特定的版本。也就是说,即便在那个时代,他也没有白手起家;这一点在HTML后来的发展过程中也体现了出来: 继往开来、承前启后,而不是另立门户、从头开始。 换句话说,这篇名为HTML Tags的文档可以算作HTML的第一个版本,但它却不是一个正式的版本。第一个正式版本,HTML 2.0,也不是出自W3C之手。HTML 2.0是由IETF,因特网工程任务组(Internet Engineering Task Force)制定的。在W3C成立之前,IETF已经发布了不少标准。但从第三个版本开始往后,W3C,万维网联盟(World Wide Web Consortium)开始接手,并负责后续版本的制定工作。 20世纪九十年代HTML有过几次快速的发展。众所周知,在那个时代要想构建网站,可是一项十分复杂的工程。浏览器大战曾令人头疼不已。市场竞争的结果就是各家浏览器里都塞满了各种专有的特性,都试图在专有特性上胜人一筹。当时的混乱程度不堪回首,HTML到底还重不重要,或者它作为Web格式的前景如何,谁都说不清楚。 从1997年到1999年,HTML的版本从3.2到4.0到4.01,经历了非常快的发展。问题是到了4.01的时候,W3C的认识发生了倒退,他们说"好了,这个版本就这样了,HTML也就这样了;HTML 4.01是HTML的最后一个版本了,我们用不着HTML工作组了。" W3C并没有停止开发这门语言,只不过他们对HTML不再感兴趣了。在HTML 4.01之后,他们提出了XHTML 1.0。虽然听起来完全不同,但XHTML 1.0与HTML 4.01其实是一样的。我的意思是说,从字面上看这两个规范的内容是一样的,词汇表是一样的,所有的元素是一样,所有的属性也都是一样的。唯一一点不同之处,就是XHTML 1.0要求使用XML语法。也就是说,所有属性都必须使用小写字母,所有元素也必须使用小写字母,所有属性值都必须加引号,你还得记着使用结束标签,记着对img和br要使用自结束标签。 从规范本身的内容来看,实际上是相同的,没有什么不同。不同之处就是编码风格,因为对浏览器来说,读取符合HTML 4.01、HTML 3.2,或者XHTML 1.0规范的网页都没有问题,对浏览器来说这些网页都是一样的,都会生成相同的DOM树。只不过人们会比较喜欢XHTML 1.0,因为不少人认同它比较严格的编码风格。 到了2000年,Web标准项目(Web Standards Project)的活动开展得如火如荼,开发人员对浏览器里包含的那些乱七八糟的专有特性已经忍无可忍了。大家都很生气,就骂那些浏览器厂商"遵守个规范就他妈的真有那么难吗?"当时CSS有了长足的发展,而且与XHTML 1.0结合得也很紧密,CSS加XHTML 1.0基本上就可以算是"最佳实践"了。虽然在我看来HTML 4.01与XHTML 1.0没有本质上的不同,但大家都接受了。专业的开发人员能做到元素全部小写,属性全部小写,属性值也全部加引号: 由于专业人员起到了模范带头作用,越来越多的人也都开始支持这种语法。 我就是一个例子!过去的10年,我一直都使用XHTML 1.0文档类型,原因是这样一来验证器就能给我帮上很大的忙,对不对?只要我写的是XHTML 1.0,然后用验证器测试,它就能告诉我是不是忘了给属性值加引号,是不是没有结束某个标签,等等等等。而如果我写的是HTML 4.01,同样的问题就变成了有效的了,验证器就不一定会提醒我了。 这就是我一直使用XHTML 1.0的原因。我估计很多人都……使用XHTML 1.0的朋友,请把手举起来。好的。HTML 4.01呢?人少多了。一直没有举手的呢,大声点,你们用什么?HTML 5,也很好!更早的呢,还有人使用更早的文档类型吗?没有了? 10年来我一直使用XHTML 1.0,就是因为验证器能够真正帮到我。有人用XHTML 1.1吗?你知道有人用吗?请举手,别放下。有人把网页标记为XML文档吗?有吗?那你们使用的就不是XHTML 1.1。 这就是个大问题。XHTML 1.0之后是XHTML 1.1,只是小数点后面的数字加了一个1,而且从词汇表的角度看,规范本身没有什么新东西,元素也都相同,属性也都相同。但对XHTML 1.1来说,唯一的变化是你必须把自己的文档标记为XML文档。在使用XHTML 1.0的时候,还可以把文档标记为HTML,而我们也正是这样做的,否则把文档标记为XML没准真会把人逼疯的。 为什么这么说呢?首先,把文档标记为XML后,Internet Explorer不能处理。当然,IE9是可以处理了。恐怕有人会讲"真是太可爱了",他们到现在居然都没有忘了这件事。这艘船终于靠岸了!不过那时候,作为全球领先的浏览器,IE无法处理接收到的XML文档类型的文档,而规范又要求你以XML文档类型来发送文档,这不把人逼疯才怪呢。 所以说XHTML 1.1有点脱离现实,而你不想把文档以XML格式发送给那些能够理解XML的浏览器,则是因为XML的错误处理模型。XML的语法,无论是属性小写,元素小写,还是始终要给属性值加引号,这些都没有问题,都很好,事实上我也喜欢这样做,但XML的错误处理模型却是这样的: 解析器如果遇到错误,停止解析。规范里就是这么写的。如果你把XHTML 1.1标记为XML文档类型,假设你用Firefox打开这个文档,而文档中有一个和号(&)没有正确编码,就算整个页面中就这一处错误,你看到的也将是黄屏,浏览器死掉了。Firefox会说: "没戏了,页面中有一个错误,你看不到这个网页了。"根据XML规范,这样处理是正确的,对Firefox而言,遇到错误就停止解析,并且不呈现其他任何内容是严格按照XML规范做的。因为它不是HTML,HTML根本就没有错误处理模型,但根据XML规范,这样做没错。 这就是为什么你不会把文档标记为XML的另一个原因。接下来,新的版本是XHTML 2,大家注意后面没有日期,因为这个规范并没有完成。 现在就说说XHTML 2,我很愿意把问题说清楚,XHTML 2实际上真是一个非常非常好的规范,确实非常好……从理论的角度来说。我的意思是说,制定这个规范的人都是非常非常有头脑的。直说吧,领导制定这个规范的家伙是斯蒂芬·彭伯顿(Stephen Pemberton),他应该是本地人,是一个聪明过人的家伙。规范本身也很了不起,如果所有人都同意使用的话,也一定是一个非常好的格式。只不过,还不够实际。 首先,XHTML 2仍然使用XML错误处理模型,你必须保证以XML文档类型发送文档;这一点不言自明: 没人愿意这样做。其次,XHTML 2有意不再向后兼容已有的HTML的各个版本。他们甚至曾经讨论过废除img元素,这对每天都在做Web开发的人来说确实有点疯了的味道。但我们知道,他们之所以这样做,理论上确实有充足的理由——使用object元素可能会更好。 因此,无论XHTML 2在理论上是多么完美的一种格式,但却从未有机会付诸实践。而之所以难以将其付诸实践,就是因为像你我这样的开发人员永远不会支持它,它不向后兼容。同样,浏览器厂商也不会,浏览器厂商必须要保证向后兼容。 为什么XHTML 1.1没有像XML那样得到真正广泛地应用,为什么XHTML 2从未落到实处?因为它违反了一条设计原理,这条设计原理就是著名的伯斯塔尔法则(Postel's Law)。大家都知道: 发送时要保守;接收时要开放。 没错,接收的时候要开放,而这也正是Web得以构建的基础。开发浏览器的人必须敞开胸怀,接收所有发送给浏览器的东西,因为它们过去一直都在接收那些不够标准的东西,对不对?Web上的很多文档都不规范,但那正是Web发展的动力。从某种角度讲,Web走的正是一条混沌发展之路,虽然混沌,但却非常美丽诱人。在Web上,格式不规范的文档随处可见,但那又怎样呢?如果所有人都能够写出精准的XML,所有文档的格式都十分正确,那当然好了。可是,那不现实。现实是伯斯塔尔法则。 作为专业人士,在发送文档的时候,我们会尽量保守一些,尽量采用最佳实践,尽量确保文档格式良好。但从浏览器的角度说,它们必须以开放的姿态去接收任何文档。 有人可能会说XML有错误处理模型,XHTML 1.1和XHTML 2都使用该模型,但那个错误处理模型太苛刻了。它绝对不符合接收时开放这个法则,遇到一个错误就停止解析怎么能叫开放呢?我们只能说它与健壮性法则(也就是伯斯塔尔法则)是对立的。 HTML 5 之后,就到了HTML 5,但HTML 5并不是由W3C直接制定的。故事的经过是这样的,到20世纪末的时候,还没有HTML工作组,W3C内部的一些人就开始琢磨了,"HTML也许还可以更长寿一点,只要我们对它稍加扩展就行了。只要把我们放在XHTML上的时间和精力拿出一部分来,就可以提升一下HTML中的表单,可以让HTML更接近编程语言,就可以让它更上一层楼。" 于是,在2004年W3C成员内部的一次研讨会上,当时Opera公司的代表伊恩·希克森(Ian Hickson)提出了一个扩展和改进HTML的建议。他建议新任务组可以跟XHTML 2并行,但是在已有HTML的基础上开展工作,目标是对HTML进行扩展。W3C投票表决的结果是——"反对",因为HTML已经死了,XHTML 2才是未来的方向。然后,Opera、Apple等浏览器厂商,以及其他一些成员说: "那好吧,不指望他们了,我们自已一样可以做这件事,我们脱离W3C。"他们成立了Web Hypertext Applications Technology Working Group(Web超文本应用技术工作组,WHATWG)——可巧的是,他们自称工作组,而不是特别小组(task force),这就为HTML 5将来的命运埋下了伏笔。 WHATWG决定完全脱离W3C,在HTML的基础上开展工作,向其中添加一些新东西。这个工作组的成员里有浏览器厂商,因此他们不仅可以说加就加,而且还能够一一实现。结果,大家不断提出一些好点子,并且逐一做到了浏览器中。 WHATWG的工作效率很高,不久就初见成效。在此期间,W3C的XHTML 2没有什么实质性的进展。特别是,如果从实现的角度来说,用原地踏步形容似乎也不为过。 结果,一件有意思的事情发生了。那是在2006年,蒂姆·伯纳斯-李写了一篇博客,说: "你们知道吗?我们错了。我们错在企图一夜之间就让Web跨入XML时代,我们的想法太不切实际了,是的,也许我们应该重新组建HTML工作组了。"善哉斯言,后来的故事情节果真就是这样发展的。W3C在2007年组建了HTML 5工作组。这个工作组面临的第一个问题,毫无疑问就是"我们是从头开始做起呢,还是在2004年成立的那个叫WHATWG的工作组既有成果的基础上开始工作呢?"答案是显而易见的,他们当然希望从已经取得的成果着手,以之为基础展开工作。于是他们又投了一次票,同意"在WHATWG工作成果的基础上继续开展工作"。好了,这下他们要跟WHATWG并肩战斗了。 第二个问题就是如何理顺两个工作组之间的关系。W3C这个工作组的编辑应该由谁担任?是不是还让WHATWG的编辑,也就是现在Google的伊恩·希克森来兼任?于是他们又投了一次票,赞成"让伊恩·希克森担任W3C HTML 5规范的编辑,同时兼任WHATWG的编辑,更有助于新工作组开展工作。" 这就是他们投票的结果,也就是我们今天看到的局面: 一种格式,两个版本。WHATWG的网站上有这个规范,而W3C的站点上同样也有一份。 如果你不了解内情,很可能会产生这样的疑问: "哪个版本才是真正的规范?"当然,这两个版本内容是一样的……基本上相同。实际上,这两个版本将来还会分道扬镳。现在已经有了分道扬镳的迹象了。我的意思是说,W3C最终要制定一个具体的规范,这个规范会成为一个工作草案,定格在某个历史时刻。 而WHATWG呢,他们还在不断地迭代。即使目前我们说的HTML 5,也不能完全涵盖WHATWG正在从事的工作。最准确的理解是他们正在开发一项简单的HTML或Web技术,因为这才是他们工作的核心目标。然而,同时存在两个这样的工作组,这两个工作组同时开发一个基本相同的规范,这无论如何也容易让人产生误解。误解就可能造成麻烦。 其实这两个工作组背后各自有各自的流程,因为它们的理念完全不同。在WHATWG,可以说是一种独裁的工作机制。我刚才说了,伊恩·希克森是编辑。他会听取各方意见,在所有成员各抒己见,充分陈述自己的观点之后,他批准自己认为正确的意见。 W3C则截然相反,可以说是一种民主的工作机制。所有成员都可以发表意见,而且每个人都有投票表决的权利。这个流程的关键在于投票表决。从表面上看,WHATWG的工作机制让人不好接受。岂止是不好接受,简直是历史的倒退。相信谁都会认为"运作任何项目都不能采取这种方式!" W3C的工作机制听起来让人很舒服。至少体现了人人平等嘛。但在实践中,WHATWG的工作机制运行得非常非常好。我认为之所以会这样,主要归功于伊恩·希克森。他的的确确是一个非常称职的编辑。他在听取各方意见时,始终可以做到丝毫不带个人感情色彩。 从原理上讲,W3C的工作机制很公平,而实际上却非常容易在某些流程或环节上卡壳,造成工作停滞不前,一件事情要达成决议往往需要花费很长时间。那到底哪种工作机制最好呢?我认为,最好的工作机制是将二者结合起来。而事实也是两个规范制定主体在共同制定一份相同的规范,我想,这倒是非常有利于两种工作机制相互取长补短。 两个工作组之所以能够同心同德,主要原因是HTML 5的设计思想。因为他们从一开始就确定了设计HTML 5所要坚持的原则。结果,我们不仅看到了一份规范,也就是W3C站点上公布的那份文档,即HTML 5语言规范,还在W3C站点上看到了另一份文档,也就是HTML设计原理。而这份文档的一位编辑今天也来到了我们大会的现场,她他就是安妮·奇泰丝(Anne Van Kesteren)。如果大家对这份文档有问题,可以请教安妮。 这份文档非常好,真的非常出色。这份文档,可以说见证了W3C与WHATWG同心协力共谋发展的历程。难道你们不觉得他们像是一对欢喜冤家吗?那他们还怎么同心同德呢?这份文档忠实地记录了他们一道做了什么,他们共同拥护什么。 接下来,我想要讲的就是这份文档。因为,既然他们能就这份文档达成共识,那么我相信,HTML 5必将是一个伟大的规范,而他们已经认可这就是他们的共同行动纲领。为此,你才会看到诸如兼容性、实用性、互用性之类的概念。即便W3C与WHATWG之间再有多大的分歧——确实相当多——至少他们还有这份文档中记录的共识。这一点才是至关重要的。正因为他们有了共识,才有了这份基于共识描述设计原理的文档。 避免不必要的复杂性 下面我就给大家介绍一些这份文档中记载的设计原理。第一个,非常简单: 避免不必要的复杂性。好像很简单吧。我用一个例子来说明。 假设我使用HTML 4.01规范,我打开文档,输入doctype。这里有人记得HTML 4.01的doctype吗?好,没有,我猜没有。除非……我的意思是说,你是傻冒。现场恐怕真有人背过,这就是HTML 4.01的doctype: <!DOCTYPE html PUBLIC "-//W3C/DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 我不记这个两行代码,不然还要记事本、要Google、要模板有什么用呢? 要是我使用XHTML 1.0呢,这个规范我都已经用了10年了。有谁记得住这个doctype吗?没错,它的长度跟HTML 4.01的差不太多: <!DOCTYPE html PUBLIC "-//W3C/DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 是不是,基本上相同。它要告诉浏览器的是: 这个文档是XHTML 1.0的文档。那么在HTML 5中,省掉不必要的复杂性,doctype就简化成了: <!DOCTYPE html> 仅此而已。好了,就连我也能过目不忘了。我用不着把这几个字符记在记事本里了。我得说,在我第一次看到这个doctype的时候——我当然以为这是一个HTML文档的doctype——被它吓了一跳: "是不是还少一个数字5啊?"我心里想: "这个doctype想告诉浏览器什么呢?就说这个文档是HTML吗?难道这是有史以来唯一一个HTML版本吗,这件事我得首先搞清楚,HTML今后永远不会再有新版本了吗?"好一副唯我独尊的架式!我错了,因为这个doctype并没有这个意思。为此,必须先搞清楚为什么文档一开头就要写doctype。它不是写给浏览器看的。Doctype是写给验证器看的。也就是说,我之所以要在文档一开头写那行XHTML 1.0的doctype,是为了告诉验证器,让验证器按照该doctype来验证我的文档。 浏览器反倒无所谓了。假设我写的是HTML 3.2文档,文档开头写的是HTML 3.2的doctype。而在文档中某个地方,我使用了HTML 4.01中才出现的一个元素。浏览器会怎么处理这种情况?它会因为这个元素出现在比doctype声明的HTML版本更晚的规范中,就不解释呈现该元素吗?不会,当然不会!它照样会解释呈现该元素,别忘了伯斯塔尔法则,别忘了健壮性。浏览器在接收的时候必须要开放。因此,它不会检查任何格式类型,而验证器会,验证器才关心格式类型。这才是存在doctype的真正原因。 而按照HTML 5的另一个设计原理,它必须向前向后兼容,兼容未来的HTML版本——不管是HTML6、HTML7,还是其他什么——都要与当前的HTML版本,HTML 5,兼容。因此,把一个版本号放在doctype里面没有多大的意义,即使对验器证也一样。 刚才,我说doctype不是为浏览器写的,这样说大多数情况下没有问题。在有一种情况下,你使用的doctype会影响到浏览器,相信在座诸位也都知道。但在这种情况下,Doctype并非真正用得其所,而只是为了达到某种特殊的目的才使用doctype。当初微软在引入CSS的时候,走在了标准的前头,他们率先在浏览器中支持CSS,也推出了自己的盒模型——后来标准发布了,但标准中使用了不一样的盒模型。他们怎么办?他们想支持标准,但也想向后兼容自己过去推出的编码方式。他们怎么知道网页作者想使用标准,还是想使用他们过去的方式? 于是,他们想出了一个非常巧妙的主意。那就是利用doctype,利用有效的doctype来触发标准模式,而不是兼容模型(quiks mode)。这个主意非常巧妙。我们今天也都是这样在做,在我们向文档中加入doctype时,就相当于声明了"我想使用标准模式",但这并不是发明doctype的本意。这只是为了达到特殊的目的在利用doctype。 下面我出一道有奖抢答题,听好: "一分钟后开始,如果你手快的话,第一个在文档前面写完doctype html,然后我用Internet Explorer打开你的文档,会触发它的标准模式,还是会触发它的兼容模式?" 答案是,这是在Internet Explorer中触发标准模式的最少字符数目。我认为这也说明了HTML 5规范的本质: 它不追求理论上的完美。HTML 5所体现的不是"噢,给作者一个简短好记的doctype不好吗?",没错,简短好记是很好,但如果这个好记的doctype无法适应现有的浏览器,还不如把它忘了更好。因此,这个平衡把握得非常好,不仅理论上看是个好主意——简短好记的doctype,而且实践中同样也是个好主意——仍然可以触发标准模式。应该说,Doctype是一个非常典型的例子。 还有一个例子,同样可以说明规范是如何省略不必要的复杂性,避免不必要的复杂性的。如果前面的文档使用的是HTML 4.01,假设我要指定文档的字符编码。理想的方式,是通过服务器在头部信息中发送字符编码,不过也可以在文档这个级别上指定: <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 同样,我也不会把这行代码背下来。我还想省下自己的脑细胞去记点别的更有价值的东西呢。不过,如果我想指定文档使用UTF-8编码,只能添加这行代码。这是在HTML 4.01中需要这样做。要是你在XHTML 1.0指定同样的编码,就得多敲一下键盘,因为你还得声明meta元素位于一个开始的XML标签中。 <?xml version="1.0" encoding="UTF-8" ?> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 在HTML 5中,你要敲的字符只有: <meta charset="utf-8"> 简短好记。我能背下来。 同样,这样写也是有效的。它不仅适用于最新版本的浏览器,只要是今天还有人在用的浏览器都同样有效。为什么?因为在我们把这些meta元素输入浏览器时,浏览器会这样解释它: "元数据(meta)点点点点点,字符集(charset)utf-8。"这就是浏览器在解释那行字符串时真正看到的内容。它必须看到这些内容,根据就是伯斯塔尔法则,对不对? 我多次提到健壮性原理,但总有人不理解。我们换一种说法,浏览器会想"好,我觉得作者是想要指定一个字符集……看,没错,utf-8。"这些都是规范里明文规定的。如今,不仅那个斜杠可以省了,而且总共只要写meta charset="utf-8″就行了。 关于省略不必要的复杂性,或者说避免不必要的复杂性的例子还有不少。但关键是既能避免不必要的复杂性,还不会妨碍在现有浏览器中使用。比如说,在HTML 5中,如果我使用link元素链接到一个样式表,我说了rel="stylesheet",然后再说type="text/css",那就是重复自己了。对浏览器而言,我就是在重复自己。浏览器用不着同时看到这两个属性。浏览器只要看到rel="stylesheet"就够了,因为它可以猜出来你要链接的是一个CSS样式表。所以就不用再指定type属性了。你不是已经说了这是一个样式表了嘛;不用再说第二次了。当然,愿意的话,你可以再说;如果你想包含type属性,请便。 同样地,如果你使用了script元素,你说type="text/javascript",浏览器差不多就知道是怎么回事了。对Web开发而言,你还使用其他的脚本语言吗?如果你真想用其他脚本语言,没人会阻拦你。但我要奉劝你一句,任何浏览器都不会支持你。 愿意的话,你可以添加一个type属性。不过,也可以什么都不写,浏览器自然会假设你在使用JavaScript。避免-不必要的-复杂性。 支持已有的内容 支持已有的内容。这一点非常重要,因为很多人都认为HTML 5很新,很闪亮;它应该代表着未来发展的方向,应该把Web推向一个新的发展阶段。这就是HTML 5,对吗?显然,我们都会考虑让Web的未来发展得更好,但他们则必须考虑过去。别忘了W3C这个工作组中有很多人代表的是浏览器厂商,他们肯定是要考虑支持已有内容的。只要你想构建一款浏览器,就必须记住这个原则: 必须支持已有的内容。 下面我们就来看一个HTML 5支持已有内容的例子。 这个例子展示了编写同样内容的四种不同方式。上面是一个img元素,下面是带一个属性的段落元素。四种写法唯一的不同点就是语法。把其中任何一段代码交给浏览器,浏览器都会生成相同的DOM树,没有任何问题。从浏览器的角度看,这四种写法没有区别。因而在HTML 5中,你可以随意使用下列任何语法。 <img src="foo" alt="bar" /> <p class="foo">Hello world <img src="foo" alt="bar"> <p class="foo">Hello world <IMG SRC="foo" ALT="bar"> <P CLASS="foo">Hello world <img src=foo alt=bar> <p class=foo>Hello world 好了,看到这几段代码,恐怕有人会说"不对不对不对。其中只有一个是对的,另外三个——说不好。"不对,应该给属性值加引号!拜托,我们可是一直都给属性值加引号的!元素名大写对吗?这种做法10年不是就被抛弃了吗? 看到HTML 5同时允许这些写法,我心里忍不住一阵阵想吐。我写了10年的XHTML 1.0,已经非常适应严格的语法了。但你必须明白,站在浏览器的角度上,这些写法实际上都是一样的。确实没有什么问题。 还有谁也感到不舒服了吗?有谁看到这些之后想"噢,这不是乱写嘛,这样做不对"?只有我这样想吗?还有别人吗? 但是,HTML 5必须支持已经存在的内容,而已有的内容就是这个样子的。不是吗?根据伯斯塔尔法则,浏览器没有别的选择。 有人可能会说"这样不行。我觉得语言本身应该提供一种开关,让作者能够表明自己想做什么。"比如说,想使用某种特定的语法,像XHTML,而不是使用其他语法。我理解这些人的想法。但我不赞成在语言里设置开关。因为我们讨论的只是编码风格或者写作风格,跟哪种语法正确无关。对于像我们这样的专业人士,我认为可以使用lint工具(一种软件质量保证工具,或者说是一种更加严格的编译器。它不仅可以象普通编译器那样检查出一般的语法错误,还可以检查出那些虽然完全合乎语法要求,但很可能是潜在的、不易发现的错误),对其他技术我们不是也在使用lint工具嘛。 比如说对JavaScript使用lint工具。JavaScript同样也是比较混乱、不严谨的例子,但它非常强大,原因恰恰是它混乱、不严谨,而且有很多不同的编码方式。在JavaScript,你可以在每条语句末尾加上分号,但不是必需的,因为JavaScript会自动插入分号……是不是听起来有点不好接受? 正因为如此,才有了像JSlint这样的工具,在道格拉斯·克劳克福德(Douglas Crockford)的网站jslint.org上面。有个网页上写着"JSlint可能会伤害你的感情。"但这确实是个非常棒的工具,它可以把JavaScript代码变得完美无瑕。如果你通过JSlint运行JavaScript,它会告诉你"好,你的JavaScript代码有效,但写法不妥。你这种编码风格啊,我不喜欢。不赞成你这样写。这样写不好。"特别是对团队,对于要使用统一的编码风格的团队,JSlint是非常方便的工具。 我个人认为,不仅对团队来说,就算是你自己写代码,也要坚持一种语法风格。从浏览器解析的角度讲,不存在哪种语法比另一种更好的问题,但我认为,作为专业人士,我们必须能够自信地讲"这就是我的编码风格。"然而,我不认为语言里应该内置这种开关。你可以使用lint工具来统一编码风格。现在就来说说lint工具。大家可以登录htmllint.com,在其中运行你的HTML 5文档,它会帮你检查属性值是否加了引号,元素是否小写,你还可以通过勾选复选框来设置其他检查项。 但这不意味着拒绝粗心大意的标记,做不做清理完全取决于你自己。我说过,因为浏览器必须支持已有的内容,HTML 5自然也不能例外。归根结底还是伯斯塔尔法则。我们始终离不开伯斯塔尔法则。 解决现实的问题 HTML 5的另一个设计原理是解决现实的问题。显而易见的是,解决各种问题的格式和规范已经比比皆是了,因此在我看来,这个原理其实是要解决理论问题,而非解决现实的问题。这条设计原理是要从理论上承认人们普遍存在的问题,消除敏感问题。 下面我来举个例子。相信这个例子有不少人都遇到过。假设我使用HTML 4或XHTML 1,页面中已经有了一块内容,我想给整块内容加个链接,怎么办?问题是这块内容里包含一个标题,一个段落,也许还有一张图片。如果我想给它们全部都可以点击,必须使用3个链接元素。于是,我得先把光标放在标题(比如说h2元素)中,写一个链接标签,然后再选中所有要包含到链接里面来的文本。接着,再把光标放在段落里,写一个链接标签,然后把段落中的文本放在链接里…… Headline text Paragraph text. 在HTML 5中,我只要简单地把所有内容都包装在一个链接元素中就行了。 Headline text Paragraph text. 没错,链接包含的都是块级元素,但现在我可以用一个元素包含它们。这样太好了。因为我碰到过类似的情形,必须给几个块级元素加上相同的链接,所有能这样写就太好了。为此,我就非常欢迎HTML 5这个新标准。 它解决了一个现实的问题。我敢说在座不少朋友都曾遇到过这个问题。 那这到底解决的是什么问题呢?浏览器不必因此重新写代码来支持这种写法。这种写法其实早就已经存在于浏览器中了,因为早就有人这样写了,当然以前这样写是不合乎规范的。所以,说HTML 5解决现实的问题,其本质还是"你都这样写了很多年了吧?现在我们把标准改了,允许你这样写了。" 求真务实 在所有设计原理中,这一条恐怕是最响亮的了——求真务实。不知道大家有没有在公司里开会时听到过这种口号: "开拓进取,求真务实。"实际上,除了作为企业的口号,它还是一条非常重要的设计原理,因为求真务实对于HTML的含义是: 在解决那些令人头痛的问题之前,先看看人们为应对这些问题都想出了哪些办法。集中精力去理解这些"民间的"解决方案才是当务之急。 HTML 5中新的语义元素就是遵循求真务实原理的反映。新增的元素不算多,谈不上无限的扩展性,但却不失为一件好事。尽管数量屈指可数,但意义却非同一般。这些新元素涉及头部(header)、脚部(footer)、分区(section)、文章(article)……,相信大家都不会觉得陌生。我的意思是说,即便你不使用HTML 5,也应该熟悉这些称呼,这些都是你曾经使用过的类名,比如class="header"/"head"/"heading",或class="footer"/"foot"。当然,也可能是ID,id="header",id="footer"。这些不都是我们已经司空见惯了的嘛。 好,举个例子吧,假设你今天写了下面这个文档。 <body> ... ... ... ... ... </body> 这里有一个div使用了id="header",另一个div使用了id="navigation",……。怎么样,都轻车熟路了吧?在HTML 5中,这些元素都可以换掉。说起新增的语义元素,它们价值的一方面可以这样来体现: "嘿,看啊,这样多好,用HTML 5新增的元素可以把这些div都替换掉。" <body> ... <nav>...</nav> ... ...</aside> <footer>...</footer> </body> 当然了,你可以这样做。在文档级别上使用这些元素没有问题。但是,假如新增这些元素的目的仅仅是为了取代原来的div,那就真有点多此一举了。 虽然在这个文档中,我们用这些新元素来替换的是ID,但在我个人看来,将它们作为类的替代品更有价值。为什么这么说呢?因为这些元素在一个页面中不止可以使用一次,而是可以使用多次。没错,你可以为文档添加一个头部(header),再添加一个脚部(footer);但文档中的每个分区(section)照样也都可以有一个头部和一个脚部。而每个分区里还可以嵌套另一个分区,被嵌套的分区仍然可以有自己的头部和脚部,是这样吧? 这四个新元素: section、article、aside和nav,之所以说它们强大,原因在于它们代表了一种新的内容模型,一种HTML中前所未有的内容模型——给内容分区。迄今为止,我们一直都在用div来组织页面中的内容,但与其他类似的元素一样,div本身并没有语义。但section、article、aside和nav实际上是在明确地告诉你——这一块就像文档中的另一个文档一样。位于这些元素中的任何内容,都可以拥有自己的概要、标题,自己的脚部。 其中最为通用的section,可以说是与内容最相关的一个。而article则是一种特殊的section。Aside呢,是一种特殊的section。最后,Nav也是一种特殊的section。 好,即便是现在,你照样可以使用div和类来描述页面中不同的部分,就像下面这样: ... ... ... ... 其中包含可能是有关内容作者的元数据,而下面会给出一些链接,差不多就这样。在HTML 5中,我完全可以说这块内容就是一个文档,通过对内容分区,使用section或article或aside,我可以说"这一块完全是可以独立存在的。"因此,我当然可以使用header和footer。 <section class="item"> ... <footer class="meta">...</footer> ... <nav class="links">...</nav> </section> 请注意,即便是footer,也不一定非要出现在下面,不是吗?这几个元素,header、footer、aside、nav,最重要的是它们的语义;跟位置没有关系。一想到footer这个词,我们总会不由自主地想,"噢,应该放在下面。"同样,我们把aside想象成一个侧边栏。可是,如果你看一看规范,就会发现这些元素只跟内容有关。因此,放在footer中的内容也可以是署名,文章作者之类的,它只是你使用的一个元素。这个元素并没有说"必须把我放在文档或者分区的下面。" 这里,请注意,最重要的还不是我用几个新元素替换了原来的div加类,而是我把原来的H2换成了H1——震撼吧,我看到有人发抖了。我碰到过不少职业的Web开发人员,多年来他们一直认为规范里说一个文档中只能有一个H1。还有一些自诩为万能的SEO秘诀同样说要这样。很多SEO的技巧其实是很教条的。所谓教条,意思就是不相信数据。过去,这种教条表现为"不行,页面中包含两个以上的H1,你就会死掉的。"在HTML 5中,只要你建立一个新的内容块,不管用section、article、aside、nav,还是别的元素,都可以在其中使用H1,而不必担心这个块里的标题在整个页面中应该排在什么级别;H2、H3,都没有问题。 这个变化太厉害了。想一想吧,这个变化对内容管理是革命性的。因为现在,你可以把每个内容分区想象一个独立的、能够从页面中拿出来的部分。此时,根据上下文不同,这个独立部分中的H1,在整个页面中没准会扮演H2或H3的角色——取决于它在文档中出现的位置。面对这个突如其来的变化,也许有人的脑子会暂时转不过弯来。不要紧,但我可以告诉你,我认为这才是HTML 5中这些新语义标记的真正价值所在。换句话说,我们现在有了独立的元素了,这些元素中的标题级别可以重新定义。 我的文档中可能会包含一个分区,这个分区中可能会嵌套另一个分区,或者一篇文章,然后文章再嵌套分区,分区再嵌套文章、嵌套分区,文章再嵌套文章。而且每个分区和文章都可以拥有自己的H1到H6。从这个意义上讲,H元素真可谓"子子孙孙,无穷匮也"了。但是,在你在编写内容或者内容管理系统的时候,它们又都是独立的,完全独立的内容块。这才是真正的价值所在。 实际上,这个点子并不HTML 5工作组拍脑门想出来的,也不是W3C最近才提出来的。下面这几句话摘自蒂姆·伯纳斯-李1991年的一封邮件,邮件是发给丹·康纳利(Dan Connolly)的。他在邮件中解释了对HTML的理解,他说: "你知道……知道我的想法,我认为H1、H2这样单调地排下去不好,我希望它成为一种可以嵌套的元素,或者说一个通用的H元素,我们可以在其中嵌套不同的层次。"但后来,我们没有看到通用的H元素,而是一直在使用H1和H2——那是因为我们一直在支持已有的内容。20年后的今天,这个理想终于实现了。 平稳退化 下一条原理大家应该都很熟悉了,那就是平稳退化。毕竟,我们已经遵守这条规则好多年了。渐进增强的另一面就是平稳退化。 有关HTML 5遵循这条原理的例子,就是使用type属性增强表单。下面列出了可以为type属性指定的新值,有number、search、range,等等。 input type="number" input type="search" input type="range" input type="email" input type="date" input type="url" 最关键的问题在于浏览器在看到这些新type值时会如何处理。现有的浏览器,不是将来的浏览器,现有的浏览器是无法理解这些新type值的。但在它们看到自己不理解的type值时,会将type的值解释为text。 无论你写的是input type="foo"还是input type="bar",现有的任何浏览器都会说: "嗯,也许作者的意思是text。"因而,你从现在开始就可以使用这些新值,而且你也可以放心,那些不理解它们的浏览器会把新值看成type="text",而这真是一个浏览器实践平稳退化原理的好例子。 比如说,你现在输入了type="number"。假设你需要一个输入数值的文本框。那么你可以把这个input的type属性设置为number,然后理解它的浏览器就会呈现一个可爱的小控件,像带小箭头图标的微调控件之类的。对吧?而在不理解它的浏览器中,你会看到一个文本框,一个你再熟悉不过的文本框。既然如此,为什么不能说输入type="number"就会得到一个带小箭头图标的微调控件呢? 当然,你还可以设置最小和最大值属性,它们同样可以平稳退化。这是问题的关键。 再看input type="search"。你也可以考虑一下这种输入框,因为这种输入框在Safari中会被呈现为一个系统级的搜索控件,右边还有一个点击即可清除搜索关键词的X。而在其他浏览器中,你得到的则是一个文本框,就像你写的是input type="text"一样,也就是你已经非常熟悉的文本框。那为什么还不使用input type="search"呢?它不会有什么副作用,没有,对不对? HTML 5还为输入元素增加了新的属性,比如 placeholder(占位符)。有人不知道这个属性的用处吗,没有吧?没错,就是用于在文本框中预先放一些文本。不对,不是标签(label)——占位符和标签完全不是一回事。占位符就是文本框可以接受的示例内容,一般颜色是灰色的。只要你一点击文本框,它就消失了。如果你把已经输入的内容全部删除,然后单击了文本框外部,它又会出现。 ...

2011-10-31 · 3 min · 578 words · -

代码覆盖率浅谈

代码覆盖率浅谈 http://www.cnblogs.com/coderzh/archive/2009/03/29/1424344.html 在做单元测试时,代码覆盖率常常被拿来作为衡量测试好坏的指标,甚至,用代码覆盖率来考核测试任务完成情况,比如,代码覆盖率必须达到80%或 90%。于是乎,测试人员费尽心思设计案例覆盖代码。用代码覆盖率来衡量,有利也有有弊。本文我们就代码覆盖率展开讨论,也欢迎同学们踊跃评论。 首先,让我们先来了解一下所谓的"代码覆盖率"。我找来了所谓的定义: 代码覆盖率 = 代码的覆盖程度,一种度量方式。 上面简短精悍的文字非常准确的描述了代码覆盖率的含义。而代码覆盖程度的度量方式是有很多种的,这里介绍一下最常用的几种: 1. 语句覆盖(StatementCoverage) 又称行覆盖(LineCoverage),段覆盖(SegmentCoverage),基本块覆盖(BasicBlockCoverage),这是最常用也是最常见的一种覆盖方式,就是度量被测代码中每个可执行语句是否被执行到了。这里说的是"可执行语句",因此就不会包括像C++的头文件声明,代码注释,空行,等等。非常好理解,只统计能够执行的代码被执行了多少行。需要注意的是,单独一行的花括号{} 也常常被统计进去。语句覆盖常常被人指责为"最弱的覆盖",它只管覆盖代码中的执行语句,却不考虑各种分支的组合等等。假如你的上司只要求你达到语句覆盖,那么你可以省下很多功夫,但是,换来的确实测试效果的不明显,很难更多地发现代码中的问题。 这里举一个不能再简单的例子,我们看下面的被测试代码: int foo(int a, int b) { return a / b; } 假如我们的测试人员编写如下测试案例: TeseCase: a = 10, b = 5 测试人员的测试结果会告诉你,他的代码覆盖率达到了100%,并且所有测试案例都通过了。然而遗憾的是,我们的语句覆盖率达到了所谓的100%,但是却没有发现最简单的Bug,比如,当我让b=0时,会抛出一个除零异常。 正因如此,假如上面只要求测试人员语句覆盖率达到多少的话,测试人员只要钻钻空子,专门针对如何覆盖代码行编写测试案例,就很容易达到主管的要求。当然了,这同时说明了几个问题: 1.主管只使用语句覆盖率来考核测试人员本身就有问题。 2.测试人员的目的是为了测好代码,钻如此的空子是缺乏职业道德的。 3.是否应该采用更好的考核方式来考核测试人员的工作? 为了寻求更好的考核标准,我们必须先了解完代码覆盖率到底还有哪些,如果你的主管只知道语句覆盖,行覆盖,那么你应该主动向他介绍还有更多的覆盖方式。比如: 2. 判定覆盖(DecisionCoverage) 又称分支覆盖(BranchCoverage),所有边界覆盖(All-EdgesCoverage),基本路径覆盖(BasicPathCoverage),判定路径覆盖(Decision-Decision-Path)。它度量程序中每一个判定的分支是否都被测试到了。这句话是需要进一步理解的,应该非常容易和下面说到的条件覆盖混淆。因此我们直接介绍第三种覆盖方式,然后和判定覆盖一起来对比,就明白两者是怎么回事了。 3. 条件覆盖(ConditionCoverage) 它度量判定中的每个子表达式结果true和false是否被测试到了。为了说明判定覆盖和条件覆盖的区别,我们来举一个例子,假如我们的被测代码如下: int foo(int a, int b) { if (a < 10 || b < 10) // 判定 { return 0; // 分支一 } else { return 1; // 分支二 } } ...

2011-10-31 · 2 min · 305 words · -

CXF Axis2

CXF Axis2 http://apache-cxf.group.iteye.com/group/wiki/1252 新一代的 Web Services 框架如 Axis2、CXF 都是由现有的项目中逐渐演化而来的,Axis2 是由大家熟悉的 Axis 1.x 系列演化过来,而 Apache CXF 则是由 Celtix 和 XFire 项目整合而生,并且刚刚发布了 2.0.2 的最新版本,不过仍是 Apache 的一个孵化项目。 Axis2 是对 Axis 进行了彻底的重写的一个新项目了,它使用了新的模块化架构,更方便于功能性的扩展等等。 Apache CXF 则是由 XFire 和 Celtix 两个现有的项目进行了重组。 问题: 如果现有的应用程序是基于 Axis 1.x、XFire 或者 Celtix 的话,那应该怎么办?都迁移到这些新的框架上去吗?但是即使是要迁移,那应该迁移到哪个框架上去呢? 如果是编写一个新的 Web Services 应用程序的话,就不存在迁移的问题了,但是哪个框架是你应当选择进行使用的呢?哪个比哪个更好呢? 对于现在的应用程序的迁移,如果你的应用程序是稳定而成熟的,并且在可预知的未来的情况下,只要很少的一些需求变更要做的话,那么保存你的体力,不要去做"劳民伤财"的迁移工作了。 如果你的现有应用程序BUG缠身,性能,功能等等都一片糟糕的话,那就要考虑迁移了,那选哪个框架呢?先比较一下它们的不同之处: Apache CXF 支持 WS-Addressing、WS-Policy、WS-RM、WS-Security和WS-I BasicProfile Axis2 支持 WS-Addressing、WS-RM、WS-Security和WS-I BasicProfile,WS-Policy将在新版本里得到支持 Apache CXF 是根据Spring哲学来进行编写的,即可以无缝地与Spring进行整合 Axis2 不是 Axis2 支持更多的 data bindings,包括 XMLBeans、JiBX、JaxMe 和 JaxBRI,以及它原生的 data binding (ADB) 。 ...

2011-10-31 · 1 min · 120 words · -

JAX-WS

JAX-WS JAX-WS规范是一组XML web services的JAVA API。JAX-WS允许开发者可以选择RPC-oriented或者message-oriented 来实现自己的web services。 在 JAX-WS中,一个远程调用可以转换为一个基于XML的协议例如SOAP。在使用JAX-WS过程中,开发者不需要编写任何生成和处理SOAP消息的代码。JAX-WS的运行时实现会将这些API的调用转换成为对应的SOAP消息。 在服务器端,用户只需要通过Java语言定义远程调用所需要实现的接口SEI (service endpoint interface) ,并提供相关的实现,通过调用JAX-WS的服务发布接口就可以将其发布为WebService接口。 在客户端,用户可以通过JAX-WS的API创建一个代理 (用本地对象来替代远程的服务) 来实现对于远程服务器端的调用。 当然 JAX-WS 也提供了一组针对底层消息进行操作的API调用,你可以通过Dispatch 直接使用SOAP消息或XML消息发送请求或者使用Provider处理SOAP或XML消息。 通过web service所提供的互操作环境,我们可以用JAX-WS轻松实现JAVA平台与其他编程环境 (.net等) 的互操作。 JAX-WS与JAX-RPC之间的关系 Sun最开始的web services的实现是JAX-RPC 1.1 (JSR 101)。这个实现是基于Java的RPC,并不完全支持schema规范,同时没有对Binding和Parsing定义标准的实现。 JAX-WS2.0 (JSR 224)是Sun新的web services协议栈,是一个完全基于标准的实现。在binding层,使用的是the Java Architecture for XML Binding (JAXB, JSR 222),在parsing层,使用的是the Streaming API for XML (StAX, JSR 173),同时它还完全支持schema规范。

2011-10-31 · 1 min · 50 words · -

GOF 23 种设计模式, Design pattern

GOF 23 种设计模式, Design pattern 在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 的书,该书首次提到了软件开发中设计模式的概念。 四位作者合称 GOF(四人帮,全拼 Gang of Four)。 单例 (Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式 [[Singleton#单例模式 Singleton]] 原型 (Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。[[prototype模式#原型模式 Prototype]] 工厂方法 (Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。 抽象工厂 (AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。 建造者 (Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。[[创建者模式-builder#创建者模式 建造者模式 Builder]] 代理 (Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。[[proxy-pattern#代理模式 proxy pattern]] 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。[[adapter]] 桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。 装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。 享元 (Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。 组合 (Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。 模板方法 (TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。[[Template-Method#设计模式 – 模板方法 Template Method]] 策略 (Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。[[设计模式-策略strategy#设计模式 – 策略 Strategy]] 命令模式 (Command):将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。 职责链 (Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。 状态 (State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。 观察者 (Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。 中介者 (Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。 迭代器 (Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。 访问者 (Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。 备忘录 (Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。 解释器 (Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。 分类 创建模式, Creational Patterns Simple Factory 简单工厂模式 https://blog.wiloon.com/?p=1399 Factory Method 工厂方法 Abstract Factory 抽象工厂模式 Prototype, 原型 Builder, 建造者 Singleton, 单例 结构模式, Structural Patterns Facade, 外观 Proxy, 代理 Adapter, 适配器 Composite, 组合 Decorator, 装饰器 https://blog.wiloon.com/?p=847 Bridge, 桥接 Flyweight, 享元 行为模式, Behavioral Patterns Template Method, 模板方法 Memento, 备忘录 Observer - 观察者 https://wiloon.com/observer Chain Of Responsibility, 责任链 Command, 命令模式 (别名: 动作模式(Action)或事务模式(Transaction)) State, 状态 Strategy, 策略 Mediator, 中介者 Interpreter, 解释器 Visitor, 访问者 Iterator, 迭代器 GoF: (Gang of Four,GOF设计模式) - 四人组 Design Patterns: Elements of Reusable Object-Oriented Software (即后述《设计模式》一书) ,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著 (Addison-Wesley,1995) 。这几位作者常被称为"四人组 (Gang of Four) “,而这本书也就被称为"四人组 (或 GoF) “书。 ...

2011-10-29 · 2 min · 379 words · -

PetStore

PetStore PetStore 是 SUN 公司推出的一个宠物商店的系统,其唯一的目的不是让你卖宠物,而是学习 J2EE 最新版本的特性的一个绝好例子。也有不少语言推出相应版本的宠物商店。 Petstore的J2EE设计模式和组件框架思想是最值得学习的两种技术,在PetStore中,真正有关宠物这个具体应用相关的代码很少,整个宠物店是构架在一系列可重用的EJB组件上,这种架构思想值得借鉴。 Petstore只是一种设计思想的展示品,离成熟品有一定距离,性能设计未考虑,.NET曾经将自己精心设计的产品与之相比,这种比较是不公平的,它如同嘲笑模特儿服装不能穿到大街上一样可笑。不过现在,更多轻量JPestore值得学习。

2011-10-29 · 1 min · 9 words · -

/proc

/proc 在GUN/Linux操作系统中,/proc 是一个位于内存中的伪文件系统(in-memory pseudo-file system)。该目录下保存的不是真正的文件和目录,而是一些“运行时”信息,如系统内存、磁盘io、设备挂载信息和硬件配置信息等。proc目录是一个控制中心,用户可以通过更改其中某些文件来改变内核的运行状态。proc目录也是内核提供给我们的查询中心,我们可以通过这些文件查看有关系统硬件及当前正在运行进程的信息。在Linux系统中,许多工具的数据来源正是proc目录中的内容。例如,lsmod命令就是cat /proc/modules命令的别名,lspci命令是cat /proc/pci命令的别名。 cat /proc/pagetypeinfo 查看内存碎片情况 cat / proc / pagetypeinfo 我看到三种types的内存区域; DMA DMA32 正常 Linux如何select一个内存区域来分配一个新的页面? 写入/读取受内存保护的进程的内存 我怎样才能减less最小的Linux进程的内存占用量 区分Java应用程序mmaped内存和Linux上的JVM mmapped内存 使用C用户空间代码读取Linux / proc接口的最佳方法是什么? 在Linux程序中跟踪积极使用的内存 找出一个进程在Linux上使用多less内存页面 OSError:无法从python subprocess.call分配内存 python subprocess.Popen错误与OSError:一段时间后不能分配内存 Shell脚本循环在CygWin下耗尽内存 在fork ()中重复的段? 这些内存区域仅为32位系统定义,而不在64位中定义。 记住这些是我们正在讨论的内核可访问的main memory 。 在32 bit (4GB)系统中,内核与用户空间之间的分割为1:3 。 含义内核可以访问1GB和用户空间3GB。 内核的1GB分割如下: Zone_DMA (0-16MB): 永久映射到内核地址空间。 出于兼容性原因,较旧的ISA设备只能处理较低的16MB主内存。 Zone_Normal (16MB-896MB): 永久映射到内核地址空间。 许多内核操作只能使用ZONE_NORMAL所以它是性能最关键的区域,并且是内核主要分配的内存。 ZONE_HIGH_MEM (896MB以上): 没有永久映射到内核的地址空间。 内核可以访问整个4GB的主内存。 内核的1GB通过Zone_DMA & Zone_Normal和用户的3GB通过ZONE_HIGH_MEM 。 使用英特尔的Physical Address Extension (PAE) ,可以获得4个额外的位来寻址主存储器,产生36位,总共可以访问64GB的内存。 增量地址空间 (36位地址 – 32位地址)是ZONE_HIGH_MEM用于映射到用户访问的主存储器 (即2GB – 4GB之间)的位置。 ...

2011-10-27 · 1 min · 80 words · -

glibc

glibc glibc 是非常底层的系统库,千万不要自己手动更新,网上有很多教训。 glibc是linux下面c标准库的实现,即GNU C Library。glibc本身是GNU旗下的C标准库,后来逐渐成为了Linux的标准c库,而Linux下原来的标准c库Linux libc逐渐不再被维护。Linux下面的标准c库不仅有这一个,如uclibc、klibc,以及上面被提到的Linux libc,但是glibc无疑是用得最多的。glibc在/lib目录下的.so文件为libc.so.6。 glib glib是GTK+的基础库,它由基础类型、对核心应用的支持、实用功能、数据类型和对象系统五个部分组成,可以在[http://www.gtk.org gtk网站]下载其源代码。是一个综合用途的实用的轻量级的C程序库,它提供C语言的常用的数据结构的定义、相关的处理函数,有趣而实用的宏,可移植的封装和一些运行时机能,如事件循环、线程、动态调用、对象系统等的API。GTK+是可移植的,当然glib也是可移植的,你可以在linux下,也可以在windows下使用它。使用gLib2.0 (glib的2.0版本) 编写的应用程序,在编译时应该在编译命令中加入pkg-config –cflags –libs glib-2.0,如: gcc pkg-config –cflags –libs glib-2.0 hello.c -o hello 使用glib最有名的就是GNOME了。 eglibc eglic是二进制兼容glibc的,就是说如果代码使用的是eglic的库,那么换成glic之后无需重新编译。glibc为了实现最优化处理,致使在空间占用上越来越为人诟病。eglibc的主要特性是更好的支持嵌入式架构,支持不同的shell(GLIBC只支持bash),支持-Os,可配置组件,稳定分支修正了一些重要Bug等。 查看 glibc 版本, glibc version ldd --version # ldd命令为 glibc 提供 dpkg -s libc6 | grep Ver https://nieyong.github.io/wiki_ny/glibc,%20eglibc%E5%92%8C%20glib%E7%9A%84%E5%8C%BA%E5%88%AB.html https://shixiangwang.github.io/home/cn/post/2020-09-28-note-about-glibc/

2011-10-26 · 1 min · 46 words · -

网关,路由

网关,路由 网关 网关实质上是一个网络通向其他网络的IP地址。 比如有网络A和网络B 网络A的IP地址范围为"192.168.1.1~192.168.1.254",子网掩码为255.255.255.0 网络B的IP地址范围为"192.168.2.1~192.168.2.254",子网掩码为255.255.255.0 在没有路由器的情况下,两个网络之间是不能进行TCP/IP通信的,即使是两个网络连接在同一台交换机 (或集线器) 上,TCP/IP协议也会根据子网掩码 (255.255.255.0) 判定两个网络中的主机处在不同的网络里。而要实现这两个网络之间的通信,则必须通过网关。 如果网络A中的主机发现数据包的目的主机不在本地网络中,就把数据包转发给它自己的网关,再由网关转发给网络B的网关,网络B的网关再转发给网络B的某个主机。网络B向网络A转发数据包的过程也是如此。 只有设置好网关的IP地址,TCP/IP协议才能实现不同网络之间的相互通信。那么这个IP地址是哪台机器的IP地址呢? 网关的IP地址是具有路由功能的设备的IP地址,具有路由功能的设备有路由器、启用了路由协议的服务器 (实质上相当于一台路由器) 、代理服务器 (也相当于一台路由器) 。 默认网关 如果搞清了什么是网关,默认网关也就好理解了。就好像一个房间可以有多扇门一样,一台主机可以有多个网关。默认网关的意思是一台主机如果找不到可用的网关,就把数据包发给默认指定的网关,由这个网关来处理数据包。现在主机使用的网关,一般指的是默认网关。 默认网关必须是电脑自己所在的网段 (将IP地址和子网掩码作与运算,得到网段) 中的IP地址,而不能填写其他网段中的IP地址。 自动网关 自动网关设置就是利用DHCP服务器来自动给网络中的电脑分配IP地址、子网掩码和默认网关。这样做的好处是一旦网络的默认网关发生了变化时,只要更改了DHCP服务器中默认网关的设置,那么网络中所有的电脑均获得了新的默认网关的IP地址。这种方法适用于网络规模较大、TCP/IP参数有可能变动的网络。 路由器 理解IP路由器原理及工作机制 一个路由器其实就是一个超小型的电脑,而且操作系统大多为Linux,但是在做这些操作的时候你可能并不知道IP路由是如何工作的。本文将助你理解IP路由的原理,以及它是如何工作的。 IP路由涉及到IP数据报文的转发。如果主机与目的主机直接相连,那么主机可以直接发送IP报文到目的主机,这个过程比较简单。例如,通过点对点的链接或通过网络共享。如果主机与目的主机没有直接相连,那么主机会将IP报文发送给默认的路由器,然后由路由器来决定往哪发送IP报文。 普通的主机与路由器之间的根本区别在于,主机不会将一个报文从一个接口转发到另一个接口,而路由器可以转发报文,大多数的多用户系统都可以被配置,从而被当作路由器来用。 因此,一个普通路由算法可以被用在路由器上,同样也可以用在一台普通主机上。当一台主机可以用作路由器时,我们通常说这台主机嵌入了路由器的功能。这种具备嵌入路由器功能的主机平常不会转发报文,除非我们对它进行了配置,使它开启这种功能。 IP层维护着一张路由表,当收到数据报文时,它用此表来决策接下来应该做什么操作。当从网络侧接收到数据报文时,IP层首先会检查报文的IP地址是否是主机自身的地址相同,如果数据报文中的IP地址是主机自身的地址,那么报文将被发送到传输层相应的协议中去。 如果报文中的IP地址不是主机自身的地址,并且主机配置了具备路由的功能,那么报文将被转发;否则,报文就被丢弃。 路由表中的数据一般是以条目形式存在,路由表条目包含以下主要的条目项: 目的IP地址: 此字段表示目标的IP地址。这个IP地址可以是某一台主机的地址,也可以是一个网络地址。如果这个条目包含的是一个主机地址,那么它的主机ID标记为非零;如果这个条目包含的是一个网络地址,那么它的主机ID被标记为零。 下一个路由器的IP地址: 为什么我们使用"下一个"的说法,是因为下一个路由器并不总是最后的目的路由器,但它很可能是一个中间路由器。条目给出下一个路由器的地址是用来转发从相应接口收到的IP数据报文。 标志: 这个字段提供了另一组重要信息,如目的IP地址(之前提到的)是一个主机地址还是一个网络地址。此外,从标志中可以得知下一个路由器(之前提到的)真的是一个路由器还是一个直接相连的接口。 网络接口规范: 一些数据报文的网络接口规范,这个规范跟随报文一起传播。 如果我们现在想简单而形象地描述路由过程,我们将会看到: 一旦主机(被配置成具备路由功能)的IP层接收到从网络侧来的数据报文,它将核实数据包中的目的IP地址,如果此IP不是主机的IP地址,那么包将通过路由表转发。 如果任何条目的第一个字段完全匹配目的IP地址或部分匹配目的IP地址,那么它将指示下一个路由器的IP地址。这是一个重要的信息,因为这些信息直接告诉主机数据包应该转发到哪一个"下一个路由器"去。而条目中所有其它的字段将提供更多辅助的信息来为路由转发做决定。 首先,路由表会去搜索一个"目的IP地址"字段与数据报文中目的IP地址完全相同的条目。这就意味着IP地址的主机ID与网络ID完全的匹配。如果找到,则数据包被发送到相应接口或中间路由器。 如果没有找到一个完全的匹配IP,那么就接着搜索相匹配的网络ID。如果找到,那么该数据报文会被转发到指定的路由器。所以我们看到,这个网络上的所有主机都通过这个路由表中的单个(这个)条目来管理。 如果上述步骤失败,即没有默认路由器,那么该数据报文最终无法被转发。任何无法投递的数据报文都将产生一个ICMP主机不可达或ICMP网络不可达的错误,并将此错误返回给生成此数据报文的应用程序。 在路由表中包含与网络相关的路由条目是一个很大的优点。其优点在于,拥有一个与完整网络相关的条目,能够避免包含此网络中所有单独的主机条目,这使得路由表的大小降到一个可收受的数量级,这样就非常好。 网关和路由器的区别 对于路由器的设置,很多朋友们都还不大了解,或许听过,但是设置的时候会很迷糊,不知道如何下手。设置宽带路由器时,你会发现在在"高级路由"设置中有两个选项: 网关和路由器。今天我们来讲讲这两个的区别。 网关 简而言之,网关是网络的进口和出口 (网关还有其他功能,如协议翻译……) ,网关定义网络的边界。 路由器使用一系列算法决定网络间的最短路径。 路由器使用静态路由或动态路由来决定网络间的最短路径。静态路由需要管理员手动设置,而动态路由使用一些协议来动态发现网络间的路径并判断最短路径。通常,对于小型网络使用静态路由,大型复杂网络使用动态路由。 现在,路由器集成了网关的功能,所以路由器也具有网关的功能。 从网关和路由器的定义来看,如果只是简单地连接两个网络,那么只需要网关就足够了。 假定只有两个网络: 网络A和网络B 要使网络A和网络B能够通信,只使用网关将这两个网络连接即可,因为只有两个网络,不需要决定网络间最短路径。 如果需要连接多个网络,为了保证网络的可靠性,网络结构需要设计为全网状或部分网状,这样,为了网络间的通信,需要网关和路由器两种设备,因为当前路由器集成了网关的功能,所以只使用路由器一种设备就可以了。 假定有4个网络: 网络A、网络B、网络C、网络D 要使这4个网络之间能够通信,另外为了保证网络的可靠性,将这4个网络进行全网状连接,如下图: 例如,此时从网络A到网络D就有两条路径,所以需要使用路由器来决定网络间的最短路径。 下面来看看宽带路由器中"高级路由"中的网关和路由器选项: 网关: 如果此宽带路由器是网络上唯一一台连接Internet的路由器,选择网关。此时宽带路由器作为网络的进/出口。计算机基础教程 路由器: 如果网络中还有其他路由器,选择路由器。 总结: 1、对于家庭共享上网,只需要使用网关即可,所以在宽带路由器中选择"网关"选项 2、对于大型企业网络内部,或大型企业网络连接Internet,由于网络中可能存在其他路由器,所以应当选择宽带路由器中的"路由器"选项,以决定网络间的最短路径 PS: 默认网关 有时在Windows中设置网络时,我们经常会看到"默认网关"的设置 ...

2011-10-23 · 1 min · 97 words · -

HTTP basic

HTTP basic get/post 1.HTTP请求格式: 在HTTP请求中,第一行必须是一个请求行 (request line) ,用来说明请求类型、要访问的资源以及使用的HTTP版本。紧接着是一个首部 (header) 小节,用来说明服务器要使用的附加信息。在首部之后是一个空行,再此之后可以添加任意的其他数据[称之为主体 (body) ]。 重定向 Redirect 重定向是指当浏览器请求一个URL时,服务器返回一个重定向指令,告诉浏览器地址已经变了,麻烦使用新的URL再重新发送新请求。 例如,我们已经编写了一个能处理/hello的HelloServlet,如果收到的路径为/hi,希望能重定向到/hello 如果浏览器发送GET /hi请求,RedirectServlet将处理此请求。由于RedirectServlet在内部又发送了重定向响应,因此,浏览器会收到如下响应: HTTP/1.1 302 Found Location: /hello 当浏览器收到302响应后,它会立刻根据Location的指示发送一个新的GET /hello请求,这个过程就是重定向: ┌───────┐ GET /hi ┌───────────────┐ │Browser│ ────────────> │RedirectServlet│ │ │ <──────────── │ │ └───────┘ 302 └───────────────┘ ┌───────┐ GET /hello ┌───────────────┐ │Browser│ ────────────> │ HelloServlet │ │ │ <──────────── │ │ └───────┘ 200 └───────────────┘ 观察Chrome浏览器的网络请求,可以看到两次HTTP请求: 并且浏览器的地址栏路径自动更新为/hello。 重定向有两种: 一种是302响应,称为临时重定向,一种是301响应,称为永久重定向。两者的区别是,如果服务器发送301永久重定向响应,浏览器会缓存/hi到/hello这个重定向的关联,下次请求/hi的时候,浏览器就直接发送/hello请求了。 重定向有什么作用?重定向的目的是当Web应用升级后,如果请求路径发生了变化,可以将原来的路径重定向到新路径,从而避免浏览器请求原路径找不到资源。 HttpServletResponse提供了快捷的redirect()方法实现302重定向。 http2 https://halfrost.com/http2-http-frames/ ...

2011-10-23 · 1 min · 147 words · -

Conditional Get

Conditional Get HTTP条件Get HTTP条件Get是HTTP协议为了减少不必要的带宽浪费,提出的一种方案。详见http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html HTTP条件Get使用的时机: 客户端之前已经访问过某网站,并打算再次访问该网站 HTTP条件Get使用的方法: 客户端向服务器发送一个包询问是否在上一次访问网站的时间后是否更改了页面,如果服务器没有更新,显然不需要把整个网页传给客户端,客户端只要使用本地缓存即可,如果服务器对照客户端给出的时间已经更新了客户端请求的网页,则发送这个更新了的网页给用户。 下面是具体的发送接受报文: 客户端发送查询请求: ```java GET / HTTP/1.1 Host: www.sina.com.cn:80 If-Modified-Since:Thu, 4 Feb 2010 20:39:13 GMT Connection: Close 下面是当没有更新时服务器的相应: ```java HTTP/1.0 304 Not Modified Date: Thu, 04 Feb 2010 12:38:41 GMT Content-Type: text/html Expires: Thu, 04 Feb 2010 12:39:41 GMT Last-Modified: Thu, 04 Feb 2010 12:29:04 GMT Age: 28 X-Cache: HIT from sy32-21.sina.com.cn Connection: close 如果服务器网页已经更新就会发送把客户端的请求当作一个普通的Get请求发送相应报文 HTTP/1.0 200 OK Date: Thu, 04 Feb 2010 12:49:46 GMT Server: Apache Last-Modified: Thu, 04 Feb 2010 12:49:05 GMT Accept-Ranges: bytes X-Powered-By: mod_xlayout_jh/0.0.1vhs.markIII.remix Cache-Control: max-age=60 Expires: Thu, 04 Feb 2010 12:50:46 GMT Vary: Accept-Encoding X-UA-Compatible: IE=EmulateIE7 Content-Length: 452785 Content-Type: text/html Age: 11 X-Cache: HIT from sy32-27.sina.com.cn Connection: close /*.......网页内容....... */

2011-10-23 · 1 min · 112 words · -

Wireshark

Wireshark Wireshark (前称Ethereal) 是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。 网络封包分析软件的功能可想像成 “电工技师使用电表来量测电流、电压、电阻” 的工作 - 只是将场景移植到网络上,并将电线替换成网络线。 在过去,网络封包分析软件是非常昂贵,或是专门属于营利用的软件。Ethereal的出现改变了这一切。在GNUGPL通用许可证的保障范围底下,使用者可以以免费的代价取得软件与其源代码,并拥有针对其源代码修改及客制化的权利。Ethereal是目前全世界最广泛的网络封包分析软件之一。 应用 Wireshark使用目的以下是一些使用Wireshark目的的例子: 网络管理员使用Wireshark来检测网络问题,网络安全工程师使用Wireshark来检查资讯安全相关问题,开发者使用Wireshark来为新的通讯协定除错,普通使用者使用Wireshark来学习网络协定的相关知识当然,有的人也会"居心叵测"的用它来寻找一些敏感信息…… Wireshark不是入侵侦测软件 (Intrusion DetectionSoftware,IDS) 。对于网络上的异常流量行为,Wireshark不会产生警示或是任何提示。然而,仔细分析Wireshark撷取的封包能够帮助使用者对于网络行为有更清楚的了解。Wireshark不会对网络封包产生内容的修改,它只会反映出目前流通的封包资讯。 Wireshark本身也不会送出封包至网络上。 发展简史 1997年底,GeraldCombs需要一个能够追踪网络流量的工具软件作为其工作上的辅助。因此他开始撰写Ethereal软件。Ethereal在经过几次中断开发的事件过后,终于在1998年7月释出其第一个版本v0.2.0。自此之后,Combs收到了来自全世界的修补程式、错误回报与鼓励信件。Ethereal的发展就此开始。不久之后,GilbertRamirez看到了这套软件的开发潜力并开始参予低阶程式的开发。1998年10月,来自NetworkAppliance公司的GuyHarris在寻找一套比tcpview (另外一套网络封包撷取程式) 更好的软件。于是他也开始参与Ethereal的开发工作。1998年底,一位在教授TCP/IP课程的讲师RichardSharpe,看到了这套软件的发展潜力,而后开始参与开发与加入新协定的功能。在当时,新的通讯协定的制定并不复杂,因此他开始在Ethereal上新增的封包撷取功能,几乎包含了当时所有通讯协定。 自此之后,数以千计的人开始参与Ethereal的开发,多半是因为希望能让Ethereal撷取特定的,尚未包含在Ethereal默认的网络协定的封包而参予新的开发。2006年6月,因为商标的问题,Ethereal更名为Wireshark。 [TCP ZeroWindow]: 接收者向发送者发送的一种窗口警告,告诉发送者你的接收窗口已满,暂时停止发送。 wireshark 时序图 菜单>统计>TCP流图形>时间序列 窗口尺寸 菜单>统计>TCP流图形>窗口尺寸 https://www.codenong.com/cs106112955/ Wireshark 过滤 port 按端口过滤 # 一个端口 tcp.port == 25 # 多个端口 tcp.port == 25 or tcp.port == 80 按目标端口过滤 tcp.dstport == 25 显示来自10.230网段的封包 ip.src == 10.230.0.0/16 wireshark http ssdp 过滤方法 http&&!(udp.dstport == 1900) ip.addr == 10.1.1.1 ip.src != 10.1.2.3 or ip.dst != 10.4.5.6 ...

2011-10-22 · 1 min · 77 words · -

ip-guard, [0x7FFFBB83E044] ANOMALY: use of REX.w is meaningless (default operand size is 64)

“ip-guard, [0x7FFFBB83E044] ANOMALY: use of REX.w is meaningless (default operand size is 64)” HKEY_LOCAL_MACHINE\SOFTWARE\TEC\Ocular.3\agent\config 字符串类型, key: hookapi_filterproc_external value: cmd.exe;wsl.exe foo.reg Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\TEC\Ocular.3\agent\config] "hookapi_filterproc_external"="cmd.exe;wsl.exe"

2011-10-19 · 1 min · 27 words · -