2012年6月25日星期一

阮一峰的网络日志

阮一峰的网络日志


台北印象

Posted: 24 Jun 2012 06:27 AM PDT

今年春天,我都待在台北。

周末和假期,我几乎走遍了这个城市的角角落落。它给我留下了很深的印象。如果你问我,台北是一个怎样的城市?我会告诉你,这是一个很用心、非常人性化、精致周到的地方。

我从自己拍的几千张照片中,选出了一部分,请大家一起看看我眼中的台北。

1.

我在桃园机场下飞机,在机场出口处看到一台"兑币机",可以将纸钞兑成硬币,也可以将硬币兑成纸钞。我刚到台湾就被触动了,因为我知道这种机器根本没有利润,只有巨大的维护成本。

2.

第二天,来到台北的马路上,我发现了另一件新鲜事。路边的公共设施铁箱,几乎都有彩绘,而且图案都不一样,让城市多了一份艺术气息。

3.

有些道路太窄,铁箱就被架到空中。

4.

台北是一个绿意盎然的城市,到处都是绿色,随处可见精心的盆栽。

5.

所有的食品都标明热量,即使是在路边的奶茶店。

6.

路标镶嵌在地面上,不会误判方向。

7.

街头路标,会注明距离多少米。

8.

公车站的站牌可以显示,下一班还有多久到站。(这种站牌貌似只出现在士林区。)

9.

候车亭还贴着二维码,手机扫一下,就能上网查看实时信息。同时,这里也是wifi热点。

10.

公车上,我看到一张"酒测检验表"。每次出车,上面就贴一张合格证,表明当日司机的酒测值为0。

11.

进入捷运站,需要刷卡。但是如果你想上厕所,可以要求临时进入。

12.

捷运站设有"夜间妇女候车专区",保障女性乘车安全。

13.

这是站台内的"纸类回收箱",防止乘客乱扔报纸。

14.

某些捷运站提供过滤水的龙头,供乘客免费饮用。

15.

更难得的是,这个水龙头上面,贴着一份《水质检测报告》,表明水质没有问题,还列出了采样时间、浊度、pH值、总溶解固体量等指标。

16.

台北的公共厕所,普遍非常干净,没有异味。这是铭传大学教学楼的一间普通男厕,只有几个平米,但是很干净,而且经过了精心布置。

17.

我还在捷运站的公共厕所内,看到贴在墙上的厕所清洁记录,上面写着负责人员的名字,每个时段都有签名。

18.

垃圾的分类管理。台北这方面做得很彻底,马路上很少有垃圾桶。

19.

公用电话亭都是wifi热点。

20.

一幢待拆的大楼,请注意底楼的装饰。

21.

道路施工地点前,通常会有一个假人。"他"手里拿着荧光棒,不停挥动。图上看不出来,但实际上他的手臂在动,因此非常醒目,有利于保护施工人员安全,尤其是在夜间。

22.

台北市立图书馆的各个分馆,都有"自修室"。这是桌上的小贴纸,上面写着:"如果有人占位,请告诉馆员;如果不想换新手机,请离开时带好自己财物;如果不想有老鼠爬过,请不要带零食和饮料;如果想要涂鸦,欢迎到图书馆做志工。"这种周到的提示语,几乎各种场合都能看到。

23.

乌来风景区的长凳。凳面的木板故意做成了波浪形,游客坐着会感到很舒服,但是制作起来显然很费事。

24.

台北美术馆旁边,行道树的底部有艺术品的介绍。虽然效果不理想,但这个创意是好的。

25.

阳明山风景区的游客中心,有免费手机充电服务。你问服务台领一把钥匙,把手机锁在箱子里充电,过一段时间回来取就可以了。我觉得,这个充电箱很赞。

26.

我去家乐福超市买牛奶,发现标签上不仅有商品价格,还有每100毫升的单位价格,非常有利于比价。

27.

内湖区的一个路口,有一块大型提示牌,上面写着"前方500米无法穿越马路,请在此路口过人行道"。

============================================

上面这些都是台北的优点,但是台北也有一些缺点。我举两个。

28.

机车是台北的主要交通工具,交通高峰期间,满街都是。车速极快,噪音震耳欲聋,破坏了这座城市安详宁静的气氛,让人感觉好像在工业区一样。

29.

台北的房价极高,超过上海,直逼东京。随便一套房子,都是几千万台币。

这么高的房价,是工商业的负担,也是年轻人的巨大压力(台北的工资与上海相差并不太大)。再联想到一些其他因素,我对台湾的长期竞争力感到担忧。

=============================================

最后,还想再贴两张照片。

30.

第一张是我在台湾见到的最震撼的东西。

这是台北二二八纪念馆的一件展品,

1947年3月12日,"二二八事件"受难者卢炳钦,在嘉义火车站被枪决。照片中是他临刑时穿的衬衫,上面至今可见斑斑血痕,胸口的破洞就是子弹打进去的地方。

下面的说明牌上写着:"(这是)卢炳钦被枪杀时穿着的衬衫,虽经过洗涤,斑斑血痕依然清晰可见。其妻林秀媚冒危险保存血衣五十年,为的是留下真实证据,控诉国府对人权的践踏。"

它说明了一件事:历史不会被忘记。即使正义迟到了五十年,也总有一天要来临。

31.

第二张,很不好意思,是我的自拍。

我从来没在这个网志上贴过自己的照片,但这次想在台北留个纪念。由于本人不上镜,因此请做好心理准备,再点击这个链接,或者就别点击了。

(完)

文档信息

2012年6月21日星期四

阮一峰的网络日志

阮一峰的网络日志


卡耐基人际关系指南

Posted: 20 Jun 2012 08:56 PM PDT

卡耐基(Dale Carnegie,1888-1955)是美国畅销书作家,主要研究人际关系和自我修养。

他的成名作是1936年出版的《如何赢得朋友和获得影响力》(How to Win Friends and Influence People),该书大获成功,英文版销量就超过1500万本,全球销量据说与《圣经》一个级别。(不知为何,中文版译名为《人性的弱点》,中学时我还以为是心理学著作。)

通常,我不看这类"人生指南"的书,因为感觉它们在推销一种陈腐的价值观,而且我也不太相信,它们真的能有多少作用。

但是,我偶然读到了这本书的大纲,大吃一惊,发现自己完全错了,它真的是一本很好的"人际关系实战指南"。这些年来,自己的一些模模糊糊的想法,在书中得到了系统的清晰表达。如何处理人际关系,如何得到一种较理想的人生,它给出了非常好的建议。

下面是我翻译的该书大纲,建议大家都来看看。

================================================

如何赢得朋友和获得影响力

作者:[美] 戴尔·卡耐基

译者:阮一峰

一、人际关系的基本技巧

1. 不要批评、谴责、抱怨。
  Don't criticize, condemn or complain.

2. 真诚地欣赏他人。
  Give honest and sincere appreciation.

3. 激发他人的渴望。
  Arouse in the other person an eager want.

二、获得他人好感的六种方法

4. 对他人真的感兴趣。
  Become genuinely interested in other people.

5. 微笑。
  Smile.

6. 所有语言中最甜蜜、最重要的声音,就是当一个人听到自己的名字。
  Remember that a person's name is to that person the sweetest and most important sound in any language.

7. 做一个优秀的听众,鼓励对方谈论他自己。
  Be a good listener. Encourage others to talk about themselves.

8. 谈对方感兴趣的话题。
  Talk in terms of the other person's interests.

9. 让对方感觉自己很重要,并且你是真诚地这样做。
  Make the other person feel important - and do it sincerely.

三、如何得到他人的支持

10. 彻底赢得争议的唯一方法,就是避免争议。
  The only way to get the best of an argument is to avoid it.

11. 尊重他人的意见,绝不说"你错了"。
  Show respect for the other person's opinions. Never say, "You're wrong."

12. 一旦发现自己不对,立刻无保留地承认。
  If you are wrong, admit it quickly and emphatically.

13. 以一种友好的方式开场。
  Begin in a friendly way.

14. 尽快让对方说"是这样的"。
  Get the other person saying "yes, yes" immediately.

15. 让他人多多发言。
  Let the other person do a great deal of the talking.

16. 让他人感觉,你说的是他的想法。
  Let the other person feel that the idea is his or hers.

17. 诚恳地站在他人的角度,看待问题。
  Try honestly to see things from the other person's point of view.

18. 对他人的想法和主张,抱有理解和同情。
  Be sympathetic with the other person's ideas and desires.

19. 诉诸更高尚的动机。
  Appeal to the nobler motives.

20. 把你的想法,用故事表达。
  Dramatize your ideas.

21. 激起对方的好胜心。
  Throw down a challenge.

四、如何做领导者

----不冒犯、也不引发怨恨地,让他人按照你的主张行事。

22. 以表扬和真诚的欣赏开场。
  Begin with praise and honest appreciation.

23. 婉转地指出他人的错误。
  Call attention to people's mistakes indirectly.

24. 批评他人之前,先谈自己的错误。
  Talk about your own mistakes before criticizing the other person.

25. 设问,而不是下达命令。
  Ask questions instead of giving direct orders.

26. 让他人有面子。
  Let the other person save face.

27. 赞扬每一个细微的进步,衷心地表达你的认可,慷慨地给出赞美之词。
  Praise the slightest improvement and praise every improvement. Be "hearty in your approbation and lavish in your praise."

28. 给他人应用的荣誉。
  Give the other person a fine reputation to live up to.

29. 不断地鼓励,让犯错看上去是一件小事。
  Use encouragement. Make the fault seem easy to correct.

30. 他人做你建议的事情时,让他们心情愉快。
  Make the other person happy about doing the thing you suggest.

================================================

译后记

翻译完这些内容,我一方面感到,它们的的确确是处理人际关系的有效法则,你照着去做,肯定能得到满意的结果;另一方面也感叹,人性并无奥妙,不过如此,以至于我们可以用编程般的法则去处理。

我还有一个强烈的感觉,就是不能极端遵守这些法则。如果你一五一十遵守它们,绝不违背,你会变成什么?

......成功者?最受欢迎的人?领袖?

我感觉,很可能变成一个政客。

(完)

文档信息

2012年6月19日星期二

阮一峰的网络日志

阮一峰的网络日志


SASS用法指南

Posted: 19 Jun 2012 12:41 AM PDT

学过CSS的人都知道,它不是一种编程语言。

你可以用它开发网页样式,但是没法用它编程。也就是说,CSS基本上是设计师的工具,不是程序员的工具。在程序员眼里,CSS是一件很麻烦的东西。它没有变量,也没有条件语句,只是一行行单纯的描述,写起来相当费事。

很自然地,有人就开始为CSS加入编程元素,这被叫做"CSS预处理器"(css preprocessor)。它的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件。

各种"CSS预处理器"之中,我自己最喜欢SASS,觉得它有很多优点,打算以后都用它来写CSS。下面是我整理的用法总结,供自己开发时参考,相信对其他人也有用。

============================================

SASS用法指南

作者:阮一峰

一、什么是SASS

SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护。

本文总结了SASS的主要用法。我的目标是,有了这篇文章,日常的一般使用就不需要去看官方文档了。

二、安装和使用

2.1 安装

SASS是Ruby语言写的,但是两者的语法没有关系。不懂Ruby,照样使用。只是必须先安装Ruby,然后再安装SASS。

假定你已经安装好了Ruby,接着在命令行输入下面的命令:

  gem install sass

然后,就可以使用了。

2.2 使用

SASS文件就是普通的文本文件,里面可以直接使用CSS语法。文件后缀名是.scss,意思为Sassy CSS。

下面的命令,可以在屏幕上显示.scss文件转化的css代码。(假设文件名为test。)

  sass test.scss

如果要将显示结果保存成文件,后面再跟一个.css文件名。

  sass test.scss test.css

SASS提供四个编译风格的选项:

  * nested:嵌套缩进的css代码,它是默认值。

  * expanded:没有缩进的、扩展的css代码。

  * compact:简洁格式的css代码。

  * compressed:压缩后的css代码。

生产环境当中,一般使用最后一个选项。

  sass --style compressed test.sass test.css

SASS的官方网站,提供了一个在线转换器。你可以在那里,试运行下面的各种例子。

三、基本用法

3.1 变量

SASS允许使用变量,所有变量以$开头。

  $blue : #1875e7; 

  div {
   color : $blue;
  }

如果变量需要镶嵌在字符串之中,就必须需要写在#{}之中。

  $side : left;

  .rounded {
    border-#{$side}-radius: 5px;
  }

3.2 计算功能

SASS允许在代码中使用算式:

  body {
    margin: (14px/2);
    top: 50px + 100px;
    right: $var * 10%;
  }

3.3 嵌套

SASS允许选择器嵌套。比如,下面的CSS代码:

  div h1 {
    color : red;
  }

可以写成:

  div {
    hi {
      color:red;
    }
  }

属性也可以嵌套:

  p {
    border-color: red;
  }

可以写成:

  p {
    border: {
      color: red;
    }
  }

注意,border后面必须加上冒号。

3.4 注释

SASS共有两种注释风格。

标准的CSS注释 /* comment */ ,会保留到编译后的文件。

单行注释 // comment,只保留在SASS源文件中,编译后被省略。

四、代码的重用

4.1 继承

SASS允许一个选择器,继承另一个选择器。比如,现有class1:

  .class1 {
    border: 1px solid #ddd;
  }

class2要继承class1,就要使用@extend命令:

  .class2 {
    @extend .class1;
    font-size:120%;
  }

4.2 Mixin

Mixin有点像C语言的宏(macro),是可以重用的代码块。

使用@mixin命令,定义一个代码块。

  @mixin left {
    float: left;
    margin-left: 10px;
  }

使用@include命令,调用这个mixin。

  div {
    @include left;
  }

mixin的强大之处,在于可以指定参数和缺省值。

  @mixin left($value: 10px) {
    float: left;
    margin-right: $value;
  }

使用的时候,根据需要加入参数:

  div {
    @include left(20px);
  }

4.3 颜色函数

SASS提供了一些内置的颜色函数,以便生成系列颜色。

  lighten(#cc3, 10%) // #d6d65c
  darken(#cc3, 10%) // #a3a329
  grayscale(#cc3) // #808080
  complement(#cc3) // #33c

4.4 插入文件

@import命令,用来插入外部文件。

  @import("path/filename.scss");

如果插入的是.css文件,则等同于css的import命令。

  @import "foo.css";

五、高级用法

5.1 条件语句

@if可以用来判断:

  p {
    @if 1 + 1 == 2 { border: 1px solid; }
    @if 5 < 3 { border: 2px dotted; }
  }

配套的还有@else命令:

  @if lightness($color) > 30% {
    background-color: #000;
  } @else {
    background-color: #fff;
  }

5.2 循环语句

SASS支持for循环:

  @for $i from 1 to 10 {
    .border-#{$i} {
      border: #{$i}px solid blue;
    }
  }

也支持while循环:

  $i: 6;

  @while $i > 0 {
    .item-#{$i} { width: 2em * $i; }
    $i: $i - 2;
  }

each命令,作用与for类似:

  @each $member in a, b, c, d {
    .#{$member} {
      background-image: url("/image/#{$member}.jpg");
    }
  }

5.3 自定义函数

SASS允许用户编写自己的函数。

  @function double($n) {
    @return $n * 2;
  }

  #sidebar {
    width: double(5px);
  }

(完)

文档信息

2012年6月11日星期一

阮一峰的网络日志

阮一峰的网络日志


互联网协议入门(二)

Posted: 11 Jun 2012 03:13 AM PDT

上一篇文章分析了互联网的总体构思,从下至上,每一层协议的设计思想。

这是从设计者的角度看问题,今天我想切换到用户的角度,看看用户是如何从上至下,与这些协议互动的。

==============================================================

互联网协议入门(二)

作者:阮一峰

(接上文)

七、一个小结

先对前面的内容,做一个小结。

我们已经知道,网络通信就是交换数据包。电脑A向电脑B发送一个数据包,后者收到了,回复一个数据包,从而实现两台电脑之间的通信。数据包的结构,基本上是下面这样:

发送这个包,需要知道两个地址:

  * 对方的MAC地址

  * 对方的IP地址

有了这两个地址,数据包才能准确送到接收者手中。但是,前面说过,MAC地址有局限性,如果两台电脑不在同一个子网络,就无法知道对方的MAC地址,必须通过网关(gateway)转发。

上图中,1号电脑要向4号电脑发送一个数据包。它先判断4号电脑是否在同一个子网络,结果发现不是(后文介绍判断方法),于是就把这个数据包发到网关A。网关A通过路由协议,发现4号电脑位于子网络B,又把数据包发给网关B,网关B再转发到4号电脑。

1号电脑把数据包发到网关A,必须知道网关A的MAC地址。所以,数据包的目标地址,实际上分成两种情况:

场景数据包地址
同一个子网络对方的MAC地址,对方的IP地址
非同一个子网络网关的MAC地址,对方的IP地址

发送数据包之前,电脑必须判断对方是否在同一个子网络,然后选择相应的MAC地址。接下来,我们就来看,实际使用中,这个过程是怎么完成的。

八、用户的上网设置

8.1 静态IP地址

你买了一台新电脑,插上网线,开机,这时电脑能够上网吗?

通常你必须做一些设置。有时,管理员(或者ISP)会告诉你下面四个参数,你把它们填入操作系统,计算机就能连上网了:

  * 本机的IP地址
  * 子网掩码
  * 网关的IP地址
  * DNS的IP地址

下图是Windows系统的设置窗口。

这四个参数缺一不可,后文会解释为什么需要知道它们才能上网。由于它们是给定的,计算机每次开机,都会分到同样的IP地址,所以这种情况被称作"静态IP地址上网"。

但是,这样的设置很专业,普通用户望而生畏,而且如果一台电脑的IP地址保持不变,其他电脑就不能使用这个地址,不够灵活。出于这两个原因,大多数用户使用"动态IP地址上网"。

8.2 动态IP地址

所谓"动态IP地址",指计算机开机后,会自动分配到一个IP地址,不用人为设定。它使用的协议叫做DHCP协议

这个协议规定,每一个子网络中,有一台计算机负责管理本网络的所有IP地址,它叫做"DHCP服务器"。新的计算机加入网络,必须向"DHCP服务器"发送一个"DHCP请求"数据包,申请IP地址和相关的网络参数。

前面说过,如果两台计算机在同一个子网络,必须知道对方的MAC地址和IP地址,才能发送数据包。但是,新加入的计算机不知道这两个地址,怎么发送数据包呢?

DHCP协议做了一些巧妙的规定。

8.3 DHCP协议

首先,它是一种应用层协议,建立在UDP协议之上,所以整个数据包是这样的:

  (1)最前面的"以太网标头",设置发出方(本机)的MAC地址和接收方(DHCP服务器)的MAC地址。前者就是本机网卡的MAC地址,后者这时不知道,就填入一个广播地址:FF-FF-FF-FF-FF-FF。

  (2)后面的"IP标头",设置发出方的IP地址和接收方的IP地址。这时,对于这两者,本机都不知道。于是,发出方的IP地址就设为0.0.0.0,接收方的IP地址设为255.255.255.255。

  (3)最后的"UDP标头",设置发出方的端口和接收方的端口。这一部分是DHCP协议规定好的,发出方是68端口,接收方是67端口。

这个数据包构造完成后,就可以发出了。以太网是广播发送,同一个子网络的每台计算机都收到了这个包。因为接收方的MAC地址是FF-FF-FF-FF-FF-FF,看不出是发给谁的,所以每台收到这个包的计算机,还必须分析这个包的IP地址,才能确定是不是发过自己的。当看到发出方IP地址是0.0.0.0,接收方是255.255.255.255,于是DHCP服务器知道"这个包是发过我的",而其他计算机就可以丢弃这个包。

接下来,DHCP服务器读出这个包的数据内容,分配好IP地址,发送回去一个"DHCP响应"数据包。这个响应包的结构也是类似的,以太网标头的MAC地址是双方的网卡地址,IP标头的IP地址是DHCP服务器的IP地址(发出方)和255.255.255.255(接收方),UDP标头的端口是67(发出方)和68(接收方),分配给请求端的IP地址和本网络的具体参数则包含在Data部分。

新加入的计算机收到这个响应包,于是就知道了自己的IP地址、子网掩码、网关地址、DNS服务器等等参数。

8.4 上网设置:小结

这个部分,需要记住的就是一点:不管是"静态IP地址"还是"动态IP地址",电脑上网的首要步骤,是确定四个参数。这四个值很重要,值得重复一遍:

  * 本机的IP地址
  * 子网掩码
  * 网关的IP地址
  * DNS的IP地址

有了这几个数值,电脑就可以上网"冲浪"了。接下来,我们来看一个实例,当用户访问网页的时候,互联网协议是怎么运作的。

九、一个实例:访问网页

9.1 本机参数

我们假定,经过上一节的步骤,用户设置好了自己的网络参数:

  * 本机的IP地址:192.168.1.100
  * 子网掩码:255.255.255.0
  * 网关的IP地址:192.168.1.1
  * DNS的IP地址:8.8.8.8

然后他打开浏览器,想要访问Google,在地址栏输入了网址:www.google.com。

这意味着,浏览器要向Google发送一个网页请求的数据包。

9.2 DNS协议

我们知道,发送数据包,必须要知道对方的IP地址。但是,现在,我们只知道网址www.google.com,不知道它的IP地址。

DNS协议可以帮助我们,将这个网址转换成IP地址。已知DNS服务器为8.8.8.8,于是我们向这个地址发送一个DNS数据包(53端口)。

然后,DNS服务器做出响应,告诉我们Google的IP地址是172.194.72.105。于是,我们知道了对方的IP地址。

9.3 子网掩码

接下来,我们要判断,这个IP地址是不是在同一个子网络,这就要用到子网掩码。

已知子网掩码是255.255.255.0,本机用它对自己的IP地址192.168.1.100,做一个二进制的AND运算(两个数位相同,结果为1,否则为0),计算结果为192.168.1.0;然后对Google的IP地址172.194.72.105也做一个AND运算,计算结果为172.194.72.0。这两个结果不相等,所以结论是,Google与本机不在同一个子网络。

因此,我们要向Google发送数据包,必须通过网关192.168.1.1转发,也就是说,接收方的MAC地址将是网关的MAC地址。

9.4 应用层协议

浏览网页用的是HTTP协议,它的整个数据包构造是这样的:

HTTP部分的内容,类似于下面这样:

  GET / HTTP/1.1
  Host: www.google.com
  Connection: keep-alive
  User-Agent: Mozilla/5.0 (Windows NT 6.1) ......
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Accept-Encoding: gzip,deflate,sdch
  Accept-Language: zh-CN,zh;q=0.8
  Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
  Cookie: ... ...

我们假定这个部分的长度为4960字节,它会被嵌在TCP数据包之中。

9.5 TCP协议

TCP数据包需要设置端口,接收方(Google)的HTTP端口默认是80,发送方(本机)的端口是一个随机生成的1024-65535之间的整数,假定为51775。

TCP数据包的标头长度为20字节,加上嵌入HTTP的数据包,总长度变为4980字节。

9.6 IP协议

然后,TCP数据包再嵌入IP数据包。IP数据包需要设置双方的IP地址,这是已知的,发送方是192.168.1.100(本机),接收方是172.194.72.105(Google)。

IP数据包的标头长度为20字节,加上嵌入的TCP数据包,总长度变为5000字节。

9.7 以太网协议

最后,IP数据包嵌入以太网数据包。以太网数据包需要设置双方的MAC地址,发送方为本机的网卡MAC地址,接收方为网关192.168.1.1的MAC地址(通过ARP协议得到)。

以太网数据包的数据部分,最大长度为1500字节,而现在的IP数据包长度为5000字节。因此,IP数据包必须分割成四个包。因为每个包都有自己的IP标头(20字节),所以四个包的IP数据包的长度分别为1500、1500、1500、560。

9.8 服务器端响应

经过多个网关的转发,Google的服务器172.194.72.105,收到了这四个以太网数据包。

根据IP标头的序号,Google将四个包拼起来,取出完整的TCP数据包,然后读出里面的"HTTP请求",接着做出"HTTP响应",再用TCP协议发回来。

本机收到HTTP响应以后,就可以将网页显示出来,完成一次网络通信。

这个例子就到此为止,虽然经过了简化,但它大致上反映了互联网协议的整个通信过程。

(完)

文档信息