博客迁出 yo2.cn

近两年以来我都是使用的 yo2.cn 提供的博客托管服务,就是说 yo2.cn 提供一个 WordPress 空间,我将域名 blog.solrex.cn 绑定到这个空间上。对 yo2.cn 的服务,总的来说,我还是基本满意的,不然我也不会一年后续费继续使用。但是一直以来的服务器不稳定,尤其是最近两个月来的宕机事件,让我对 yo2.cn 的服务失去了信心。09 年 3 月 14 日到 17 日,09 年 5 月 12 日到 15 日,两个月里两次长达三天的宕机事件在我的 Google Analytics 中划出了两个漂亮的谷底!我只好说,拜拜了 yo2。

以前之所以选择 yo2.cn 的服务,主要原因是(1)懒得折腾 WP 系统(2)它的服务器在国内,教育网用户可以无障碍访问(至少我女朋友在使用 CERNET)。这次将博客迁移到国外主机上,可能会造成部分教育网用户无法访问,请见谅。如果您希望继续关注此博客,请使用 Google Reader抓虾等在线阅读器订阅此博客的 RSS

现在博客的系统和主题和原来保持一致,域名也没有变化,所以对一般读者来说,访问没有任何影响。在某些网络状况下,可能速度会比原来慢一点儿;DNS 没有刷新的网络,可能要等待blog.solrex.cn域名记录的刷新;在一些存在缓存的浏览器中,可能要重刷一下缓存。

对于我来说,却是方便了许多,得到了对 WordPress 系统的完全控制,也没有了关键字的过滤,使用起来就没那么窝心了。

谈谈 CoolSIP

说明:本文有一些内容是基于本人的合理猜测。如果您知道更多细节,请不吝指出,但最好请提供事实依据,而不是仅仅指责我主观臆测,不尊重事实。我不知道事实,才会猜测,我如果知道事实,就不用猜测了。

CoolSIP 是清华大学信息网络工程研究中心建设的 IPV6“下一代互联网应用示范平台”提供的一个在 IPV6 网络上运行的 VoIP 软件,该软件提供了主机间通话和主机拨打传统 PSTN 电话的功能。目前该服务仅提供给 IPV6 教育和科研网用户使用,注册该服务需要 edu.cn 或者 ac.cn 后缀的大学或科研机构电子信箱。测试期间是免费的,但需要用在线时长换取话费。

我这里呢,就是说几句闲话,谈谈我对这个软件和服务的看法。

1. CoolSIP 的知识产权问题

我对 CoolSIP 软件的结构并不清楚,但基本可以肯定的一点是 CoolSIP 使用了开源的 osipeXosip。不用逆向工程该软件,查看 CoolSIP 帐户信息的保存位置就可以知道,CoolSIP 的帐户信息保存在 C:Documents and SettingsUsernameeXosip 目录下。

由于 osip 遵从的是 LGPL 协议,eXosip 遵从的却是 GPL 协议,那么从我有限的对知识产权的了解(关于 LGPL 和 GPL 可以参考这里),CoolSIP 也应该遵从 GPL 协议(对这点有问题您可以在评论中指出)。而目前来看,清华大学信息网络工程研究中心并没有发布 CoolSIP 的源代码,而且 CoolSIP 貌似将 osip 和 eXosip 库静态链接进了程序里(大概有隐藏的意图),那么可以认为他们并不认可 GPL 许可证——不过他们还没有错误地在安装文件中包含一份私有版权声明。

另外,http://ngmylife.wirelesslan.edu.cn/multimedia.html 页面中说:“当eTone出现无法登录的问题时,可以使用CoolSIP试试。”可以猜测 eTone 和 CoolSIP 有非常紧密的关系,而 eTone 又是一款流行 VoIP 软件“快门” 的前身,那么我对“快门”软件的版权也持谨慎地怀疑态度——不过我更倾向于快门不大可能犯这种错误。

2. CoolSIP 本身的程序设计问题

CoolSIP 是一个极不成熟的软件,使用过程中居然会出现程序错误,点“忽略”才能继续运行的情况;由于其版本历史仅仅显示到 2007 年 9 月 3 日 ,我想其对 SIP 协议的实现是存在问题的,例如在拨打一个通话中的电话号码时,CoolSIP 不会提示对方正在通话中。总之,该软件除了是 sip6.edu.cn 提供的 VoIP 服务的官方客户端以外,几乎一无是处。

3. CoolSIP 的 VoIP 服务

虽然 CoolSIP 客户端没有什么优点,但是 sip6.edu.cn 的 VoIP 服务器端对 SIP 协议的实现应该还算很标准的。由于 CoolSIP 使用了 eXosip 库,那么我就尝试使用另一款使用 eXosip 库的遵从 GPL 协议的开源软件 Linphone 尝试连接了一下 CoolSIP 服务器,居然能正常连接。

并且 Linphone 显示出比 CoolSIP 更友好的用户体验,例如:Linphone 支持 Windows 和 Linux 系统,更完整地支持 SIP 协议,支持自定义电话联系人列表,多帐户同时在线,通话统计记录显示,多种音频编码,更好的视频支持。像上面提到的 CoolSIP 不支持的“您拨打的电话正在通话中”提示,也可以在 Linphone 中听到。

官方提供的专门客户端 CoolSIP 竟然不如一个开源的通用客户端 Linphone,这大概是“下一代互联网应用示范平台”服务的一个笑柄吧。

PS: 使用 Linphone 登录 CoolSIP 的服务器,需要 libexosip2 和 libosip2 版本大于 3.3,我的经验表明 3.1 会出现较多问题。推荐手动依次编译 libosip2->libeXosip2->linphone。Windows 版的可执行安装程序包含了这两个库,所以不存在库版本低的问题。

内网穿透反向隧道代理技术

本文的主要目的是利用使 ssh 服务器(外网)通过客户端(内网)代理上网以及反向控制客户端(内网),不需要网络管理员权限,不需要 NAT。即可上网主机 A 位于内网,不可上网主机 B 位于外网,A 能直接访问 B,但 B 无法访问防火墙内的 A,这样 B 就可以使用 SSH 隧道访问 A 主机上的代理服务器上网。(估计有这种变态需求的人只存在于大学中)

B(210.77.*.*)---->(210.77.*.*)FW(192.168.0.*)|--->(192.168.0.*)A---->(192.168.0.*)FW(123.*.*.*)---->Internet
B(210.77.*.*)< ----(210.77.*.*)FW(192.168.0.*)-----(192.168.0.*)A<----(192.168.0.*)FW(123.*.*.*)<----Internet

一、代理

首先在客户端上安装 socks 代理(HTTP 代理可以使用 Squid,同理)。socks 代理软件使用 Dante。Dante 的启动以及配置需要手动调整,下面是 Dante 的配置文件 /etc/sockd.conf:

compatibility:reuseaddr
internal:0.0.0.0 port = 1080
external:eth0
logoutput:/var/log/sockd/sockd
clientmethod:none
method:none
user.privileged:root
user.notprivileged:solrex
connecttimeout:60
iotimeout:86400

## client access rules
client pass {
 from: 127.0.0.1/0 port 1-65535 to: 0.0.0.0/0
 log: connect disconnect
}

## server operation access rules
#allow bind to ports greater than 1023
pass {
  from: 0.0.0.0/0 to: 0.0.0.0/0 port gt 1023
  command: bind bindreply udpassociate udpreply
  log: connect disconnect
}

pass {
  from: 0.0.0.0/0 to: 0.0.0.0/0 port 1-65535
  protocol: tcp udp
  log: connect disconnect
}

#allow outgoing connections (tcp and udp)
pass {
  from: 127.0.0.1/0 to: 0.0.0.0/0
  command: bind bindreply connect udpassociate udpreply
  log: connect disconnect
}

#allow replies to bind, and incoming udp packets
pass {
   from: 0.0.0.0/0 to: 0.0.0.0/0
   command: bind bindreply connect udpassociate udpreply
   log: connect error
}

#log the rest
block {
   from: 0.0.0.0/0 to: 0.0.0.0/0
   log: connect error
}

下面是 Dante 的启动脚本 /etc/init.d/sockd:

#!/bin/sh
set -e

. /lib/lsb/init-functions

[ -f /usr/local/sbin/sockd ] || exit 0

[ ! -f /etc/sockd.conf ] && exit 1
SOCKD_CONF="-f /etc/sockd.conf"

SOCKD_OPTS="-D"

case "$1" in
  start)
    # Start daemons.
    log_daemon_msg "Starting Dante socks proxy server" "sockd"
    if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sockd.pid --exec /usr/local/sbin/sockd -- $SOCKD_OPTS; then
	    log_end_msg 0
	else
	    log_end_msg 1
	fi
    ;;
  stop)
    # Stop daemons.
    log_daemon_msg "Stoping Dante socks proxy server" "sockd"
	if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sockd.pid; then
	    log_end_msg 0
	else
	    log_end_msg 1
	fi
	;;
  restart)
    log_daemon_msg "Restarting Dante socks proxy server" "sockd"
	start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sockd.pid
	if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sockd.pid --exec /usr/local/sbin/sockd -- $SOCKD_OPTS; then
	    log_end_msg 0
	else
	    log_end_msg 1
	fi
	;;
  *)
    log_action_msg "Usage: /etc/init.d/sockd {start|stop|restart}\n"
    exit 1
esac

exit 0

二、ssh 服务器

服务器端 ssh 服务器最好采用 Openssh,Windows 下应该使用 Cygwin 运行 sshd,FreeSSHd 实践证明崩溃比较频繁。同一台机器的 Windows 和 Linux 上运行的 ssh 服务器最好使用相同的 host key,将 /etc/ssh/ 下面的文件保持一致即可。最好配置服务器为使用公钥进行登录验证,这样能使用自动脚本进行端口映射。

三、手动建立隧道(客户端到服务器端口映射)

用下面命令建立客户端到服务器的端口映射,将客户端的 socks 代理端口 1080 映射到服务器的端口 8080。这样服务器就可以通过自己的 8080 端口反向隧道到客户端的 socks 代理 1080 端口上网。

ssh -C -f -N -g -o PreferredAuthentications=publickey -R SERVER:8080:127.0.0.1:1080 USRNAME@SERVER
# 参数含义:
# -C: 要求对数据进行压缩
# -f:要求 ssh 执行完交互后进入后台运行
# -N:不用建立一个终端
# -g:允许远程服务器连接客户端转发端口
# -R SERVER:8080:127.0.0.1:1080:将客户机(127.0.0.1)的 1080 端口绑定到服务器(SERVER)的 8080 端口。
# USRNAME@SERVER:ssh服务器的用户名和密码
# -p 3022:ssh服务器的端口

为了方便控制,最好也将客户端的 ssh 服务器端口映射到服务器端,服务器端就可以通过登录自己的 8022 端口来登录客户端的 ssh 服务器:

ssh -C -f -N -g -o PreferredAuthentications=publickey -R SERVER:8022:127.0.0.1:22 USRNAME@SERVER

这样两台被防火墙隔开的主机就能实现双向控制。

四、自动建立隧道

手动建立隧道的缺陷是服务器端必须长期开机,并且连接只能用户在客户端手动发起。可以考虑间接的办法,比如使用两台主机均可访问的服务器作为跳板,或者客户端自动登录聊天软件,利用聊天软件接受指令。下面给出一种使用共享服务器的方法:

#!/bin/bash
# {start|stop|restart:username:ipaddress}

COMMAND="stop"
SERVER="0.0.0.0"
USRNAME=""
PORT="22"

INFOURL="http://someserver.com/somepage"

SSHOPTS="-C -f -N -g -o PreferredAuthentications=publickey -o StrictHostKeyChecking=no"

get_server_info()
{
  #info=`wget -nv -O - $INFOURL 2> /dev/null | iconv -f gbk -t utf8 |
        grep -o -e "{.*}" | tr -d '{}'`
  info=`wget -nv -O - $INFOURL 2> /dev/null | iconv -f gbk -t utf8 |
        sed -n "/{*}/s/.*{\(.*\)}.*/\1/p"`
  COMMAND=${info%%:*}
  SERVER=${info#*:}
  USRNAME=${SERVER%:*}
  SERVER=${SERVER#*:}
}

tunneling_status()
{
  tun_ps=`ps aux | grep "ssh -C" | wc -l`
  if [ $tun_ps -gt 4 ]; then
    echo -n "running"
  else
    echo -n "died"
  fi
}

start_tunneling()
{
  ssh $SSHOPTS -R 3128:127.0.0.1:3128 ${USRNAME}@${SERVER} -p $PORT
  ssh $SSHOPTS -R 8022:127.0.0.1:22 ${USRNAME}@${SERVER} -p $PORT
}

failsafe_tunneling()
{
  ssh $SSHOPTS -R 8022:127.0.0.1:22 ${USRNAME}@${SERVER} -p $PORT
}

stop_tunneling()
{
  killall -e ssh
}

echo -n "[`date +%F\ %R`] "
get_server_info

case "$COMMAND" in
  start)
    if [ $(tunneling_status) = "running" ]; then
      echo "Starting ssh tunneling.(started, do nothing)"
    else
      echo "Starting ssh tunneling."
      start_tunneling
    fi
    ;;
  restart)
    if [ $(tunneling_status) = "running" ]; then
      echo "Restarting ssh tunneling."
      stop_tunneling
      start_tunneling
    else
      echo "Restarting ssh tunneling."
      start_tunneling
    fi
    ;;
  stop)
    if [ $(tunneling_status) = "running" ]; then
      echo "Stoping ssh tunneling."
      stop_tunneling
    else
      echo "Stoping ssh tunneling.(stoped, do nothing)"
    fi
    ;;
  failsafe)
    echo "Starging ssh tunneling.(failsafe mode)"
    failsafe_tunneling
    ;;
  sleep)
    echo "Sleeping."
    exit 0
    ;;
  *)
    echo "Unrecogenized server command ($COMMAND)."
    exit 1
    ;;
esac

exit 0

将上面脚本加入 crontab 每十分钟运行一次,就能实现在服务器端对客户端进行有限的控制。

那些 ssh 教我的事

我以前以为 ssh 只能登录主机执行命令,ssh 教我它还会 scp;

我以为会 scp 很厉害了,ssh 教我它还会 sftp;

我以为会 sftp 了不得了,ssh 教我它还会 sshfs;

我以为会 sshfs 已经相当牛了,ssh 教我它还能把服务器端口绑定到本机端口(ssh -L);

我以为把服务器端口绑定到本机端口就已经上天了,ssh 教我它还能把本机端口绑定到服务器端口(ssh -R)...

然后,我怨念已久的共享上网终于实现了!

PS: 用软件还得选老牌开源软件,openssh 那么多年没更新了,在 Windows 下用 cygwin 运行都比 freesshd 稳定,不得不赞一个。Win 下的一些软件,窗口搞得花里胡哨的,功能和稳定性却不知道放到第几位了,跟人一样,长得好看的未必靠谱。

IPV6 获取地址却无法使用的解决方案

最近我的 WinXP 经常无法连接 IPV6 站点,但是 IPV6 地址的获取是正常的,同一台电脑上的 Ubuntu IPV6 工作也正常。经过一些摸索发现可能是以下两个原因造成的:

1. 分配到 2002 开头的 IPV6 地址并使用了它。2002::/16 格式的地址是 6to4 的地址,不是 native 的 IPV6 地址,所以在 IPV4+V6 双栈网络中不应该使用 2002::/16 格式的地址。执行 ping6 ipv6.google.com 可以看到自己使用的是什么 IPV6 地址。

之所以会产生 2002::/16 格式的地址,一个很可能的原因是网络中的 Windows Vista 操作系统默认会发送 IPV6 的路由器公告。使用

netsh interface ipv6 show interface "本地连接"

命令可以查看本地连接的参数,其中有一条:“发送路由器公告”,一定要设置为“否”。如果您的这个选项是“是”,那么您可以使用这个命令关闭它:

netsh interface ipv6 set interface “本地连接” advertise=disabled

如果获得的全部是 2002 开头的地址,可以使用下面命令进行重分配:

netsh interface ipv6 reset

2. IPV6 的路由表(网关)不对。tracert6 ipv6.google.com 就能看到本机是经过什么路由到 ipv6.google.com 的。如果从第一跳就显示连接超时,应该就是路由表出了问题。

两个问题的解决方案如下:

netsh interface ipv6 set prefixpolicy 2001::/16 1 1 persistent

上面这条命令的意思是设置 Windows 更偏好使用 2001 开头的 IPV6 地址,避免使用 2002 开头的地址。如果您 ping ipv6.google.com 使用的是 2001 开头的地址,那么您不必执行上面这条命令。

netsh interface ipv6 add route 2001::/16 "本地连接" fe80::21a:30ff:fe4f:7000 persistent

上面这条命令的意思是为 2001 开头的 IPV6 地址使用正确的网关 fe80::21a:30ff:fe4f:7000(中科院某公寓)。这个网关可能随着用户所在网络的不同而不同,简单点儿的方法可以去看正常用户的 ifconfig 网关地址。

之后执行 ping6 ipv6.google.com 看能否 ping 通,如果能 ping 通就说明 IPV6 工作正常了。

如果您经过以上两步之后仍然无法解决问题的话,您可以使用 netsh interface ipv6 reset 命令来重置所有修改。

PS:

1. 如何确定网络中哪些主机在发送路由器公告?

2002 后面的两个字段就是该主机的 IPV4 地址,比如 2002:3b41:177e:8:18fc:7649:9e1d:2880,其中 3b41:177e 从 16 进制显示换算成 IPV4 的 10 进制显示地址就是 59.65.23.126。一般来说,V4 地址的分配更有规律,您可以从 V4 地址大致确定该主机的位置。

2. 如何确定虚假的路由记录?

一般来说,IPV6 地址的最后 4 个域应该从网卡的物理地址中获得,假设网卡物理地址是:00-17-31-94-99-EA,在 3,4 字节之间插入 FFFE 换成 EUI-64 格式是:00-17-31-FF-FE-94-99-EA,再对第一个字节的第二位取反,就变成 02-17-31-FF-FE-94-99-EA,然后装载到 IPV6 的本地地址中,就变成本地地址 fe80::217:31ff:fe94:99ea。根据网段的不同,在前面加上 4 个网络域,就是主机的公网地址 2001:xxxx:xxxx:xxxx:217:31ff:fe94:99ea。

由于双栈路由器是使用同一个网卡提供 V4 和 V6 的路由,那么路由器的 V4 地址和 V6 地址的物理地址是一样的。通过 ping gateway_ipaddress_v4,然后 arp -a 看 V4 的网关地址对应的物理地址,与上面 V6 网关本地地址中获得的物理地址相对照,就可以确定某路由记录是否为可用的记录。

The Gold Old Tools: Pic and Chem

我本来只想写一下 pic 这个小工具,因为很少有中文资料介绍其用法。但是写下来没想到一个小软件联系到那么多典故,更让我对当年的贝尔实验室高山仰止。The gold old days never come again.

目录
1. Pic 的作者
2. 一个 Pic 的简单例子
3. 一个复杂的例子
4. 关于 chem 的典故
5. 在 LaTeX 中使用 pic

1. Pic 的作者

Pic,我敢打赌大部分读者没有听说过这个软件(或者说语言),但是我也敢打赌大部分读者听说过它的作者。

所以我只好从它的作者 Brian W. Kernighan 开始介绍了。不过也许用不着我介绍,假如你学过 C 语言,并且碰巧读过那本经典的 The C Programming Language(K&R);假如你使用 Linux,并且碰巧用过 AWK;或者你不小心学了一门编程语言,并且碰巧你学会写的第一个程序叫做“Hello, world”,那么你都应该感谢 Kernighan。没错, K&R 和 AWK 中的 K 都是代表 Kernighan,而且 Kernighan 是第一个使用 “Hello, world” 的人

2. 一个 Pic 的简单例子

Pic,是 Kernighan 写的一个图像排版软件,它主要用来作为 troff 中图片的预处理工具。简单点儿来说,pic 就是用来画特定一类图的工具,比如流程图、状态图、Petri~网、化学分子式等等。就像可以用写代码的方式写文档一样(TeX),我们也可以用写代码的方式画图,pic 就是这样一种语言。我们来看一个简单的例子(来自 More Programming Pearls):

.PS
ellipse "Source" "Code"
arrow
box "Compiler"
arrow
ellipse "Object" "Code"
.PE

将上面代码保存成一个 compiler.pic 文件,然后执行下面命令:

$ pic compiler.pic | groff | ps2eps > compiler.eps

我们就能得到名为 compiler.eps 的图像,下面这张图是使用 convert 命令从 compiler.eps 转换成的 png 图像:

Compiler(无法看到此图,可能因为您无法连接国外网站)

其实 Linux 下的 pic 是 GNU 版本的 gpic,groff 也是 GNU 版本的 troff,它们是都是被 GNU 重写了的自由软件版本的 pic 和 troff。

上面编译的步骤是,先用 gpic 将 compiler.pic 预处理为 troff 文档,然后用 groff 生成 ps 文件,然后用 ps2eps 将 ps 文件转化为 eps 图片。由于它们都是从标准输出打印文件,所以我们就用管道将这三个命令连接了起来,并且最后将标准输出重定向到 eps 文件。

3. 一个复杂的例子

看到这些,可能有人就怀疑说,这图很简单嘛,用 Photoshop 或者 GIMP 也花费不了多长时间,我干吗要再去学一门语言呢!那么,你尝试用 Photoshop 画一下下面这张图片。

Chemical Structure(无法看到此图,可能因为您无法连接国外网站)

画这张图的代码如下:

.cstart
    R:  benzene pointing right
        bond left from R.V4 ; HO
        bond -150 from R.V3 ; CH3O
        bond right from R.V1 ; C
        double bond up from C ; O
        bond right from C ; N
        bond 45 ; C2H5
        bond 135 from N ; C2H5
.cend

看到这,可能有人感叹说,哇,pic 真厉害!错(or 半错?),上面这段代码不是 pic 语言,而是 chem 语言。pic 是 troff 的预处理器,而 chem 又是 pic 的预处理器。所以上面这段代码的编译命令是:

$ chem.pl chem.chem | pic | groff | ps2eps > chem.eps

chem.pl 先把上面代码转换成 pic 语言,然后再用 pic 进行处理。

4. 关于 chem 的典故

关于 chem,还有一段典故:

话说当年(别问我,我不知道是哪一年)一个星期一的下午,Kernighan、 Jon Bentley 和一个同在贝尔实验室的化学家 Lynn Jelinski 闲扯了一会儿,Lynn 就向他俩抱怨在文档中插入化学结构式实在太麻烦了。正好 Kernighan 刚写了 pic,就想,咦,这不可以用 pic 画吗?于是那天晚上 K&B 就写了一个简单的前端。Lynn 一看,哎,不错!他们仨花了一个星期时间完成了 chem 语言,还在 Computers & Chemistry 杂志上发了篇 paper,名字叫做:Chem - a program for phototypesetting chemical structure diagrams。

别着急,还没完。话说当年(1990) GNU 要搞自由软件版本的 troff,开始重写 troff,把前端中的 pic, tbl, soelim 和 eqn 都重写了,就剩下画数学公式的 ideal 和 chem 没有重写。到现在你看你自己 Linux 中的 info groff,在 Introduction->Preprocessor 的最后还能找到:“There are other preprocessors in existence, but, unfortunately, no free implementations are available. Among them are preprocessors for drawing mathematical pictures (`ideal') and chemical structures (`chem').“

时间慢慢到了 2006 年 10 月 19 号,一个叫 Bernd Warken 的小子在 groff 的邮件列表中吼了一嗓子:哈哈,我用 Perl 重写了 chem!然后维护者 Werner LEMBERG 大叔就说:Great! 才有了我上文中的 chem.pl,原始的 chem 是用 AWK 语言写的。但是 chem.pl 到现在还没有到 groff 的正式发行版中,原因很囧,groff 在 2006 年 10 月 16 号以后还没有 release 新版本。所以如果你想使用 chem.pl,只能到 groff 的 cvs 仓库下载:http://cvs.savannah.gnu.org/viewvc/groff/contrib/chem/?root=groff

5. 在 LaTeX 中使用 pic

上面只是简单介绍了一下用 pic 做 eps 图片的过程,但是 pic 还可以用到 LaTeX 中,这样简单的图片就直接在 TeX 里写了。比如我们的第一个图片,就可以这样在 TeX 中使用:

\documentstyle{article}
\begin{document}
  \newenvironment{centergpic}{}{\begin{center}~\box\graph~\end{center}}
     \begin{centergpic}
.PS
ellipse "Source" "Code"
arrow
box "Compiler"
arrow
ellipse "Object" "Code"
.PE
     \end{centergpic}
\end{document}

.PS 和 .PE 一定要在行首。将上面文件保存成 compiler.tex,用 pic 预处理一下,再用 latex 编译:

$ pic -t compiler.tex > compiler1.tex
$ latex compiler1.tex
$ dvipdfmx compiler1.dvi

就能生成含有该图的 pdf 文件。

PS:若有人对 Pic 感兴趣,请阅读 Eric S. Raymond 大叔写的 “Making Pictures With GNU PIC”。你没看错,就是写《大教堂和集市》和《Unix 编程艺术》那个 Raymond 大叔。你也不用下载它,到 /usr/share/doc/groff/ 下面找一找吧,那个叫做 pic.ps.gz 的。

Aspell: 程序员的拼写检查利器

作为一个程序员,尤其是非英语母语国家(ESL or EFL)的程序员,写出漂亮的注释可能要比写出漂亮的代码更难。就比如 Eric 的“来自英语母语国家的”女友就有 “Programmers are English-challenged.“ 的评论。

那么如何在程序的注释中避免犯一些低级语法或者拼写错误呢?Eric 也在 Some useful tools for you to write English articles on Linux 中推荐了几个小工具。我这里算拾人牙慧,稍微写一点儿我非常欣赏的 Aspell 拼写检查工具。

Aspell 是一个强大的拼写检查工具,尤其是对于程序员来说。在 Linux 下,大部分程序员应该是用 Vim 或者 Emacs 写代码,它们有内建拼写检查功能,比如 vim 可以用 :setlocal spell spelllang=en_us 开启对美式英语的拼写检查。不过很少人会安装或者使用拼写检查功能,不是每个人都喜欢写代码时面对一堆高亮的词组(当它们不仅检查注释时,哦,天那!)。幸运的是,我们有 Aspell。

Aspell 使用方法非常简单,比如只想检查 C 或者 C++ 风格的注释和字符串中的拼写错误,就可以用这样的命令:

$ aspell --mode=ccpp -c test.cpp

终端里就会列出一个一个注释中的错误,并给出修改意见。接下来的工作就很简单了,按照窗口下面每个键对应的功能,选择更换单词或者忽略该单词。如下图所示:

Aspell 拼写检查工具(无法看到此图,可能因为您无法连接国外网站)

Aspell 还有更多模式,比如检查 HTML, TeX, XML, Perl 等等一些文档或程序中的拼写,更多内容就请看 Aspell 的帮助吧。

Aspell 的用户习惯保存在 ~/.aspell.en.prepl 和 ~/.aspell.en.pws 两个用户自定义替换和忽略单词列表里,可以通过备份或者修改这两个列表来改变 aspell 对某些单词拼写检查的策略。

Feedburner 订阅数图标显示解决办法

很多人以前都用过 Feedburner 烧制自己的 rss feed,但是由于众所周知的原因,Feedburner 的 rss 输出在中国网,封天下无法访问了(不信您可以点击一下我博客右侧的 Feedburner 图标)。虽然用 Google Reader 订阅 Feedburner 的 feed 仍然不受影响,但是博客订阅数图标无法正常显示,所以很多人好奇我是如何让 Feedburner 订阅数图标仍然显示在博客侧栏的

更新:刚才写完,我想看看 feed 有没有更新,忽然发现 Feedburner 的 rss 可以访问了,试了试订阅数图标,也能正常显示了。GFW 打盹了?我说这几天 Feedburner 订阅数增加那么快呢。总之我这篇文章算是白写了......呜呜呜呜,没有提前重现问题的后果。

又更新:12 月 23 日,我又无法访问 feedburner 的 RSS 了,才一天那!看来我这篇文章还算没有完全白写,不能幻想 GFW 的仁慈。

其实我以前是用的这篇博客里的方法。这个方法要求你有个国外主机空间,碰巧我能使用师兄的空间,把那篇文章中的 feedburner.php 上传到空间里就可以使用了。

但是使用过程中我发现这个方法有个很严重的问题:不支持并发访问。这是由于它的方法太生硬,先读取自己文件的内容,如果文件中写的时间比当前时间早 4 个小时,就下载新的订阅数图标,重写自身文件(修改更新时间那一行),并将订阅数图标附在文件最后。注意到这里,它会重写自身文件,一个 php 文件读取自己,改一行再重新写入自己,那么如果多个用户同时访问该文件,那不就乱套了?

所以我对它进行了修改,改为一个相对干净的方法:抓取订阅数统计图标保存为一个 gif 文件,每次访问 php 文件时,php 去判断当前时间与该 gif 文件最后修改时间的差,如果大于过期时间,就重新抓取订阅数统计图标更新 gif 文件,最后将访问重定向到 gif 文件。点击这里 http://solrex.org/feedburner.php 查看效果。

具体 php 代码如下(其实我本想用 file_get_contents 函数的,但发现不好用,只好还用这个原来的 httpSocketConnection 函数了,显得冗长了些):

<?php
$username = "username"// Feedburner account name.
$expire_time = 3600;   // Expire time(in second, 3600s = 1 hour).

$fb_url = "feeds.feedburner.com";
$gif_path = "/~fc/".$username."?bg=99CCFF&fg=444444&anim=0";
$localfile = "fb_".$username.".gif";

if(!function_exists('httpSocketConnection')){
  function httpSocketConnection($host, $method, $path, $data)
  {
    $method = strtoupper($method);
    if ($method == "GET") {
      $path.= '?'.$data;
    }
    $filePointer = fsockopen($host, 80, $errorNumber, $errorString);
    if (!$filePointer) {
      return false;
    }
    $requestHeader = $method." ".$path."  HTTP/1.1\r\n";
    $requestHeader.= "Host: ".$host."\r\n";
    $requestHeader.= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0\r\n";
    $requestHeader.= "Content-Type: application/x-www-form-urlencoded\r\n";
    if ($method == "POST") {
      $requestHeader.= "Content-Length: ".strlen($data)."\r\n";
    }
    $requestHeader.= "Connection: close\r\n\r\n";
    if ($method == "POST") {
      $requestHeader.= $data;
    }          
    fwrite($filePointer, $requestHeader);
    $responseHeader = '';
    $responseContent = '';
    do {
      $responseHeader.= fread($filePointer, 1);
    }
    while (!preg_match('/\\r\\n\\r\\n$/', $responseHeader));
    if (!strstr($responseHeader, "Transfer-Encoding: chunked")) {
      while (!feof($filePointer)) {
        $responseContent.= fgets($filePointer, 128);
      }
    } else {
      while ($chunk_length = hexdec(fgets($filePointer))) {
        $responseContentChunk = '';
        $read_length = 0;
        while ($read_length < $chunk_length) {
          $responseContentChunk .= fread($filePointer, $chunk_length - $read_length);
          $read_length = strlen($responseContentChunk);
        }
        $responseContent.= $responseContentChunk;
    &nb
sp;   fgets($filePointer);
      }
    }
    return chop($responseContent);
  }
}

function get_fbcount($host, $path, $file)
{
  $content = httpSocketConnection($host, 'GET', $path, NULL);
  $fp = fopen( $file,"w" );
  fwrite($fp, $content);
  fclose($fp);
}

if (file_exists($localfile)) {
  $last_modified = filemtime($localfile);
  if ( date('U') - $last_modified > $expire_time) {
    get_fbcount($fb_url, $gif_path, $localfile);
  }
} else {
  get_fbcount($fb_url, $gif_path, $localfile);
}
Header("Location: $localfile");
?>

将上述代码保存为一个 php 文件,比如 fb_username.php,修改用户名和过期时间,上载到国外或者港台能正常访问 Feedburner 的主机空间中,您就可以在网页中用:

<img src="http://your.host.domain/fb_username.php" style="border: 0pt none ;" alt="Feedburner">

来引用 Feedburner 订阅计数图标了。由于这个 php 脚本按照用户名保存 gif 图标,您可以在一个服务器上为多人提供引用,只需修改 php 文件的 usrname 一项,并上传为另一个 php 文件,您也可以将这两个变量改为 php 文件的参数(不建议这样做,因为会被别人利用)。

您也可以在这里下载到 feedburner.txt,要记得将其后缀改为 php 哦。

A Chance For Linux and Freeware

连着忙了几天,今天闲话几句。

关于微软正版验证

我家希希说:“我要被黑屏了,怎么办呀?我要学 Linux!”

我说:“没关系,你把自动更新服务关掉就行了。”

我家希希说:“我还是想学 Linux!”

微软准备在 2008 年 10 月 20 日对中国用户启动的 WGA 计划这几天被吵得沸沸扬扬,搞得几乎人人自危,生怕被黑屏了。本人的评论如下:

  • 对此措施,我持欢迎态度。这件事起码给中国的盗版用户提了个醒:软件是有知识产权的!用盗版的操作系统很开心,用盗版的应用软件也很开心,到最后是中国整个落后的软件产业不开心,软件民工们也不开心。

  • 对于效果,我持保留态度。我相信中国盗版产业中广大劳动人民的智慧!

  • 对于影响,我持乐观态度。这是一个 Linux 和免费软件的机遇。此次 WGA 计划一出,势必会督促那些已经有学习其它操作系统愿望的用户真正动起手来,也会使那些使惯了盗版 Office 的人考虑一下免费的优秀国产软件 WPS Office,进而认识到许多优秀的免费软件并不比收费软件差

最后友情提醒一下,WPS Office 2007 目前已更新到支持 M$ Office 2007 文件格式( .docx, .xlsx, .pptx ),永中也于本月 13 号推出了免费的永中 Office 2009 个人版,支持 Windows 和 Linux 平台;免费的国产软件 Foxmail 和"进口软件" Thunderbird 都可以替代 Outlook ; Ubuntu 8.10 Linux 操作系统还有 14 天就发布了。

关于看论文

最近被老师逼着快速浏览了大量论文,发现自己以前看论文的效率还是太低。眼高手低的毛病总是改不了,做研究还是要潜心进去。

关于看书

每天睡前逼着自己看一会儿书效率挺高的。豆瓣上我在读的书已经超过二十本了,平日很难分出大块时间看,目前已经利用睡前十分钟解决了两本。躺床上用台灯看书的感觉蛮惬意的,置身于黑暗中的一小片光明,仿佛又回到了中学时代。当然这也得益于现在宿舍的环境布置,床头就是写字桌,要是像以前在中关村时住上铺的话,势必就会影响室友的睡眠了。

关于 writeos

九月份更新了两次,十一假期无暇写字,第三章到现在还没写完,我希望十月底能完成发布第二个版本。上个星期一个墨西哥的小伙子加我 Gtalk,问这本书的问题,开始我还以为是华裔,后来知道人家根本不懂中文,没办法只好推荐他去看代码注释。也许等我再完成两章之后,会和某些朋友合作开始将它翻译成英文。

豆瓣好友地图

想知道您的豆瓣好友都分布在地球的哪个角落吗?想把这些家伙都揪出来标记在一张地图上吗?也许您想尝试一下这个东东:豆瓣好友地图。(本文最下面就是 solrex 的豆瓣好友地图) 这是一个完全以兴趣为引导的小项目,欢迎您提出您的宝贵建议来帮助完善它,当然了,如果您能顺便在博客里进行一下推广就更感谢了!

LionGG 是我的一个好朋友,他和 Classicning 共同开发了这个豆瓣好友地图。很遗憾那,我很久以前就有了这个想法,而且曾经眉飞色舞地向室友描述了这个应用,只是苦于时间和知识的局限没有实现,否则这个页面就会 host 在 solrex.cn 下了 :)

豆瓣好友地图的开发基于豆瓣、Google Map、Google Chart 和 HeatMap 提供的 API 接口。如果您是 GIS 的爱好者,或者有足够的好奇心,您也可以把这个页面的 js 脚本下载下来看个究竟,没准会找到对您有用的东西。

它的作者 LionGG 毕业于南京大学地理信息科学系,目前在中科院地理所攻读博士学位。此公平常有事儿没事儿爱写一些有关地理信息系统(GIS)的文章,也是一个积极的“社会观察者”,他的博客在这里,感兴趣的话就去逛逛吧!

豆瓣好友地图

Google 词典和 Gtalk 翻译机器人

由于我工作的机器配置实在太低,1.8GHz CPU, 256M 内存,40G 硬盘,跑一个 Ubuntu 也是非常吃力,我平常只敢开三四个程序,这样每次切换程序还要等个十几秒,唉!

虽然我 Ubuntu 里也装了 Stardict 星际译王,但我轻易不敢再开一个程序,太慢了!现在我发现一个非常有意思的东西解决了我的困扰,Gtalk 翻译机器人。其实这是我在尝试另一项服务 Google 词典时无意中发现的,很奇怪的是,我记得曾经看到一个 Google 官方的关于 Gtalk 翻译机器人的页面,怎么再也找不到了?只搜索到一个 Gtalk 开发组的博客上的新闻链接

添加 Gtalk 翻译机器人很简单,就是选择添加好友,好友 email 为:语言缩写2语言缩写@bot.talk.google.com。比如汉英翻译的机器人名字是:zh2en@bot.talk.google.com,英汉翻译的机器人名字是:en2zh@bot.talk.google.com。当然了,还有更多,点上面的新闻链接可以查看。

用这个机器人有什么好处呢?一是方便,直接在聊天软件里就可以查词。就像我用那么落后的机器,打开一个词典软件能让它假死半分钟,而 IM 软件总是会开着的,打开一个聊天窗口显然方便和快很多;还有一个好处是 Google 将你的聊天内容记录到 Gmail 里,那么过一段时间整理一下聊天记录就是一个非常好的生词表 :)。查找聊天记录很简单,只需要在 Gmail 上方的搜索栏中输入:from: en2zh@bot.talk.google.com 再点搜索即可。

Goolge 词典也是非常好用的,但不知道为什么在 Google 首页上点 Language Tools 进去以后却没有词典的链接,只有到 more->even more 中找 Translate 才有。

香港免费 VPN HOWTO

香港网站 Prairie Dog 提供了免费的 VPN 帐户,不要问我这个帐号能干嘛,自己去看。

申请免费 VPN 帐号地址:http://www.pdog-vpn.com/freeaccount.php(一个IP只能申请一个,多账号会被封)。

我不得不感叹中国网民的行动速度,我上午才申请的 pdog 的帐号,下午发文时就无法注册了。不过还有许多好心人收集这些免费 VPN 的信息,请点击 http://blog.119797.com/article/free-vpn/

Windows HOWTO:
http://www.pdog-vpn.com/setup.php

由于它没有 Linux HOWTO,这里我就提供一个

Ubuntu HOWTO:

安装 VPN 软件:
$ sudo apt-get install pptp-linux network-manager-pptp network-manager-vpnc

使用 VPN:
1. 点击 Ubuntu 系统通知栏中的网络连接图标,选择 VPN Connections->Configure VPN。
2. 点 Add 出来对话框之后,点 Forward 进入第二步,Connect to: 选择 PPTP Tunnel,再 Forward。
3. Connection 标签中 Connection Name 填个随便什么名字,我这里就用 pdog,Gateway 填 Prairie Dog 发给您的邮件中的主机名 xxx.pdog-vpn.com,然后 Forward, Apply,Close。
4. 点击网络连接图标,然后 VPN Connections->pdog,弹出窗口,输入用户名密码。然后,网络连接图标就会出来一个金黄色的小锁。
5. 然后访问某些可以查看 IP 地址的网站,比如 www.ip138.com,就会发现自己的 IP 地址变成了来自“香港特别行政区”。

这样,您就可以访问那些由于某些原因无法正常访问的网站了。

PS:我刚刚发现我域名下所有子域名都被我的域名服务商删除,而且无法添加,难道又是因为奥本海默运?

PSS:给域名服务商打了个电话,一个小时后看来已经部分恢复了,也可以添加子域名了。接线员给我的回复是 DNS 设置少了一个,所以系统更新时被当作错误信息删除掉了,看来我过于敏感了。

金山公司花巨资为 WPS Office 从 Design Science 引进了公式编辑器

提起 Design Science 公司大家可能并不熟悉,但是说到 M$ Office 里的公式编辑器和 MathType,大概大家就不会觉得陌生了。对,公式编辑器和 MathType 都是 Design Science 公司的产品。

这不是一则新闻,不过也不旧,这件事发生在 2008 年 5 月 8 日,金山公司对外宣布金山公司巨资购买公式编辑器 回馈WPS 用户。Design Science 也在网页上显著位置(高于微软)将金山公司列为战略合作伙伴

自从半年前放弃盗版的 M$ Office 投入到 WPS Office 永久免费的个人版阵营之后,我不断地发现 WPS Office 的优点(当然了,其最大的优点是免费)。WPS Office 能对 Office 文档格式(.doc, .ppt, .xsl)相当完美的兼容,与 OpenOffice 那种兼容不是一个数量级的。我最喜欢的还有一个功能:直接导出 pdf 格式文档。但是其缺乏公式编辑器也让我很苦恼,就在前几天,在完成一门课程作业时(中国的老师怎么那么喜欢用 Word 文档留作业且作为提交格式啊?),我不得不到一个在线的 TeX 网站去生成要用到的公式图片,再下载了插入到 WPS 文档中。

今天我到金山的网站去下载更新的 WPS 的时候(我讨厌自动更新),忽然在一个角落里发现了 WPS 添加公式编辑器的新闻,这个消息让我很振奋。这个功能将大大地提高 WPS Office 的易用性,而且可以促使更多人有理由放弃盗版的 M$ Office。我将其记录在我的博客里,也希望看到的人能够(至少尝试一下)迁移到 WPS Office 平台上工作,为减少中国被国外诟病的软件侵权行为出一分力。(我女朋友现在就一直使用 WPS,因为当初我骗她说这是精简版的 Office ^_^,我室友也在我的强烈呼吁下部分转移到了 WPS Office 平台。)

其实我应该算是 WPS 的老用户了,在 1998 年,我刚开始接触电脑的时候,学会用电脑打字使用的就是 WPS,当时记忆深刻的就是它的崩溃频率,基本上一上午至少要崩溃两次,辛辛苦苦打的东西唰就全变成乱码了。不过 WPS 也在发展,它曾两度(2001年和2007年)荣获国家科技进步二等奖,大概是国产软件获得的国家级最高奖项了吧。金山公司2007年8月份做出了将个人版免费发布的决定,我认为这个决定将为中国办公软件的正版化做出不可磨灭的贡献。

Google Code

受到某同学的提醒,今天我把我的两个小项目中科院IP网关登录客户端《使用开源软件-自己动手写操作系统》源代码转移到了 Google Code 上。

CAS NET 本身就是遵从 GPL 协议的,所以我就将所有内容都转移到了 Google Code,原有的官方主页也设置了301永久重定向到 Google Code 页。

《使用开源软件-自己动手写操作系统》的电子书内容是遵从的 CC 协议,所以并没有将电子书的 TeX 源码放到 Google Code 上,只是将书中示例程序的源代码放了上去。原有的官方主页还保留,主要用做发布所有源码(TeX+Demo)用。虽然最近比较忙,第三章还是写了一部分,大概月底能发布第三章吧(不敢保证,因为期末考快到了!)。不像博客,写书总得需要大块的时间,而我能挤出来的时间确实不多。唉,我也想早点儿把它完成。

最近在申请两个公司的暑期实习生,微软和IBM。个人比较喜欢 IBM CRL 那个 Security 的职位,只是,现在由不得咱们挑啊!

从安全的角度理解——为什么要使用 Google 的服务?

我很喜欢 Google 的一些服务 Gmail, Reader, Documents等等,而且我也一直大力倡导周围的人使用 Google 的服务。在我看到一些人仍在使用 163, sina 的信箱,抓虾的在线订阅器的时候,我不禁为他们通信的安全性担心。为什么使用 Google 的服务?一个很重要的原因是:因为它更安全。

目录:

1. 得到抓虾用户名密码的例子
2. 嗅探和可嗅探网络
3. 为什么 Google 更安全?
4. 为什么 163, sina, 抓虾 不安全?
5. 如何使用 Google 提供的安全服务?
6. 使用 Google 提供的安全服务的额外好处

1. 得到抓虾用户名密码的例子

首先,来看一个截图,看看国内某著名在线订阅器网站抓虾网对用户密码的保护有多脆弱:

Wireshark_Zhuaxia

请大家注意截图的最下方,能否看到这一行字:
email=solrex%40gmail.com&password=testtest&persistentCookie=true
solrex@gmail.com 是我在抓虾的注册帐号,而后面的 password 大家应该知道是什么东西吧!(不用试我的帐户,我的密码已经改了。)

有人会好奇这张截图怎么得到的,其实这是我在自己的电脑上用 Wireshark(一款著名的网络数据包分析软件,其前身是 Ethereal) 对通过我网卡的到抓虾网数据包进行监控的截图。Wireshark 实际上就是一款嗅探器,它能记录经过指定网络接口的所有数据包并进行分析。

2. 嗅探和可嗅探网络

为了解释如何才能得到上面的数据包,首先要介绍一下网络嗅探的原理:

嗅探,是一种黑客的窃听手段,一般是指使用嗅探器对数据流的数据截获。由以太网的知识我们知道,在以太网的冲突域中,每台主机的网卡都能接触到所有的数据包,如果数据包的目的地址是自己,网卡就接收数据包,并将包的内容向上层传递;如果数据包的目的地址不是自己,就将该包丢弃。那么如果网卡接收所有的数据包并对其进行分析呢?这就是所谓的“混杂模式”,将网卡设置为混杂模式后,就可以接收所有包,进而对同一网络中的其它主机的通信内容进行监听,这就是 Wireshark 进行嗅探的原理。

需要说明的一点是,在当前的网络下,直接进行嗅探并没有那么容易。上面所说的情况,只在以太网的冲突域中才能实现,而当前交换机的广泛使用,将冲突域限制到交换机和主机两点之间,除了自己没有其它主机,当然也无法直接对其它主机的通信内容进行监听。如果在交换网络下达到嗅探的目的,必须通过其它办法,比如 ARP 欺骗,这超出了本文的讨论范围,就不予介绍了。

虽然在交换网络下无法对其它主机进行直接嗅探,但是我们无法保证在我们的数据包经过的防火墙或者网关时候不会被监听。就比如在实验室的网络环境下,实验室的管理员在网络出口的防火墙处对数据包进行分析是易如反掌的事情。

所以我们总结一下,用户通信的数据包被监听可能发生在几种情形下:一、共享网络,网络用户通过集线器连接到网络;二、交换网络的结点不可信任,比如公司网络的出口防火墙管理员不可信;三、缺乏安全机制的无线网络,比如学校为学生提供的无线网络连接(用 WEP 加密传输的网络可以认为是缺乏安全机制);四、有ARP欺骗的交换网络。

由于很多网站的登录 session 是使用的 http 协议,在此协议下,用户名和密码都是通过明文传输的(抓虾和 sina 就是一个例子),所以当用户处在上述的网络环境下时,很有可能数据包被别人监听到。而数据包一旦被监听和分析,得到用户的信息易如反掌,南京大学小百合 BBS 最近的一篇文章:你还敢在教室中享受无线吗? ,就是一个很生动的例子。

3. 为什么 Google 更安全?

首先,因为 Google 采用了 https 协议来处理用户登录请求。https(Hypertext Transfer Protocol over Secure Socket Layer) 协议是指加强安全的 http 协议,正如它名字所示,它采用 SSL 来保证数据的加密传输。举个很有证明力的事实,如果你有任何一个银行的网上银行帐号,请打开你的网银登录窗口,查看上面的地址栏内容开头是不是:https://xxx.xxx.com/xxxx 。没有任何一家银行采用 http 协议处理网银登录请求,这说明了什么?http 协议不安全。

其次,因为 Google 使用可选的 https 协议来提供内容传输服务。虽然 Google 在其任何服务的登录请求处理中都是使用 https 协议,但是在认证完用户之后,和 Google 服务器的连接就转回到了 http 协议。这样虽然 Google 的用户名和密码不能被窃听到了,可服务的内容,比如 Gmail 邮件的邮件内容就会被恶意用户窃听到。那么如何使整个通信的内容都受到保护呢,就需要使用 Google 提供的可选 https 服务,只需要在你的浏览器地址栏内容的最前面 http:// 换成 https:// 即可。

4. 为什么 163, sina, 抓虾 不安全?

sina 和 抓虾 没有提供任何的帐户信息和内容的安全传输功能,所以在课堂上演示嗅探器工作方式的时候,演示者一般都会首先拿 sina 开刀,原因很简单,它是个大网站。

163 呢,比前面两个好一点儿,它提供了可选的帐户信息的加密传输功能,就是在登录 163 信箱的时候,在登录框下面有一个“增强安全性”的选项,如果勾选了增强安全性选项,163 就会用 https 来处理用户的登录请求。但是 163 仍然没有提供对用户内容的加密传输功能,即 163 的所有邮件在网络上都是明文传输

5. 如何使用 Google 提供的安全服务?

如果用户希望自己的帐户信息和传输内容都受到保护的话,那么就应该使用 Google 提供的 https 连接登录 Google 服务。比如Gmail 的 https 入口是:https://mail.google.com/ ,Google Reader 的 https 入口是:https://www.google.com/reader/ 。在 Google 其它的服务中,用户也可以简单地通过将地址栏的 http:// 换成 https:// 来选择使用安全传输。

6. 使用 Google 提供的安全服务的额外好处

使用安全的加密传输能保证自己传输的信息不被别人获取,这是显而易见的好处,但是使用 Google 的安全服务还有一点额外好处:避免自己的网络访问被关键词过滤。

有过访问敏感站点经验的同志可能都知道,如果网页中包含某些关键词,连接往往会被重置。就比如用户使用 Google Reader 订阅了某个激进的博客的RSS FEED,如果使用传统的 http 连接,当文章中包含敏感关键词时,Google Reader 就会与服务器断开连接。如果使用加密传输的话,传输内容就避免了被关键词过滤,就不会发生类似连接被重置的情况。

用 Google Reader 生成 Blogroll(侧栏链接列表) 和博客推介广告

我一直认为 Google Reader 是最好的在线博客阅读器,但是它的功能不仅仅是博客阅读器,下面介绍 Google Reader 还能为 Bogger 做的两个小功能。

一、用 Google Reader 生成 Blogroll(侧栏链接列表)

相信很多 blogger 都比较头疼于如何设置 blogroll:用博客程序自带的吧,不一定好看(尤其是Wordpress 自带的);自己写 HTML 吧,太费劲,尤其在添加/删除链接时,很麻烦s。那看看我用 Google Reader 生成的 blogroll 吧(也可直接到我博客主页查看效果):

Blogroll Demo by Google Reader

还是挺漂亮的吧,怎么生成的呢?其实方法很简单,如果你使用 Google Reader 来管理自己的博客订阅,只需要把你要链接的朋友的博客订阅放在一个 folder 里,比如我的就是 BlogRoll, 然后到 Settings->Tags 设置里,将 BlogRoll 这个 tag 的权限设置为 public 即可,如下图所示:

Blogroll Setting in Google Reader

看到 BlogRoll 那一行最后一个链接没?“add a blogroll to your site”,下面的操作我就不说了吧。(注意,需要博客程序支持添加 JavaScript源码,MSN Space和新浪一流恐怕没办法。)

这样做好之后,当你想在 blogroll 里添加/删除一个朋友的链接时,就可以直接在 Google Reader 里对 BlogRoll 文件夹添加/移除订阅即可。别忘了 Google Reader 也支持修改链接的名字哦!

二、用 Google Reader 生成博客推介广告

有自己的个人网站也是一件很麻烦的事情,不知道个人主页里应该写什么内容,咱不是什么牛人,也没什么可写嘛。如果页面挺空,就可以把自己的最新博客文章链接放上去啊,至少要在自己的个人主页上推广一下自己的博客嘛。看看我在一些页面上放的“博客推介广告”:

Blog AD By Google Reader

其实这是一个小 trick,Google Reader 不是支持将订阅内容共享出来嘛(就是上面那张图里的“add a clip to your site”),那么我当然可以只共享自己的博客内容喽。将自己的博客订阅单独放在一个 folder 里,然后“add a clip to your site”,^_^。

这样每次你一更新自己的博客,个人主页的链接就跟着更新了,当然了,也可以在某些支持 js 脚本的网站上做签名档...

三、(你不是学数学的吧,不是只有两个功能吗?)顺便推广一下 Firefox

知道上面的几个截图怎么生成的吗?没有使用任何其它程序,只用了 Firefox 的一个插件:Screen Grab ,功能强大吧!

Ubuntu 8.04 长期支持桌面版本 Linux 发布

[本博讯,北京时间2008年4月24日19点] Canonical 公司发布了最新的开源 Linux 操作系统发行版:Ubuntu8.04 LTS(长期支持)桌面版,Canonical 也同时发布了 Ubuntu 8.04 长期支持服务器版。

Ubuntu(音:oo-BOON-too[u:'bu:ntu:]) 8.04 LTS(Hardy Heron) 是 Canonical 公司自 Ubuntu 6.06 LTS 以来发行的第二个长期支持版本,它将提供对桌面版 3 年,服务器版 5 年的长期升级和服务支持。Linux Foundation 2007 年的调查结果显示,Ubuntu Linux 已经成长为桌面市场的后起之秀,占据了 Linux 桌面版本的头把交椅。同样,这次 Ubuntu 8.04 将以更完善的硬件支持,更漂亮的用户界面,更新更多的软件包选择,更方便的用户交互掀起一场 Linux 桌面系统的大革命。

Ubuntu 8.04 的完整下载地址列表:http://www.ubuntu.com/getubuntu/downloadmirrors

Ubuntu 8.04 的系统安装指导,常用程序安装,桌面效果截图,可以在这里找到。

如果你是新手也没有关系,一个小软件 Wubi 允许你在 Windows 下像安装应用程序一样轻松安装 Ubuntu Linux

另外,中国北京的清北DIY俱乐部目前宣布向全国提供免费 Ubuntu 光盘派送,每人可免费申请一套Ubuntu 8.04系统光盘(1DVD+1CD),详情见http://quickbest.com.cn/discuz/thread-26153-1-1.html

PS: 秀一个别人做的 Ubuntu Sticker:

Image

为什么 Gtalk 不支持视频聊天?

这是一个网友问我的问题,当时我的回答是:大概 Jabber 协议不支持吧,这个问题你应该去问 Google。但是当我搜索了一下 Gtalk 的帮助和网络上的内容后,居然没有发现这个问题的解答(可能是我搜索技术不到家),这就变成了一个有趣的问题。

为什么 Gtalk 不支持视频聊天?在咨询了 Wikipedia 之后,我发现我的回答基本是对的,因为 Gtalk 使用的聊天协议不支持。

Gtalk 使用的通信协议叫做 Jabber,因特网工程工作小组(IETF)已经将 Jabber 的核心 XML 串流协定以 XMPP(Extensible Messaging and Presence Protocol) 之名,正式列为认可的即时通讯及 Presence 技术。而 XMPP 的技术规格已被出版为 RFC 3920RFC 3921。所以在一般的讨论中,我们不区分 Jabber 和 XMPP。

从上面的介绍中我们也可以看出,XMPP 的技术是基于可扩展标记语言(XML)的,所以呢它有它的很多优点,比如:分布式(想像一下用电子邮件聊天),可扩展(XML命名空间的特性),弹性佳(可用在不同领域,比如网络监控,游戏),多样性(Jabber协议的公开性使你不必被一款聊天软件绑架),安全(利用已有的SASL及TLS技术)。

但是也正因为 XML,XMPP 协议有一些缺点,正是这些缺点给 Gtalk 带来了限制。

缺点一:Scalability(规模可伸缩度?)--> Gtalk 不支持群组聊天(Group Chat)。

XMPP 的可伸缩度不好,当进行多用户聊天或者提供发布/订阅服务时,XMPP 会带来很多 overhead(网络开销),这样会大大降低整个系统的通信效率。一些组织正在通过添加协议扩展来解决这个问题,就比如 2007 年 6 月 Google 在 Gtalk Gadget(像我们通常在Gmail窗口中看到那个)中加入了 Group Chat 功能,但是直到现在桌面版 Gtalk 仍然不支持 Group Chat。

缺点二:No binary data(无法传输二进制数据)--> Gtalk 不支持视频聊天。

XMPP 协议的数据包通常是被编码成一个长 XML 文档,限制了它直接传输原始二进制数据流的能力,所以使用 XMMP 协议的聊天工具的文件传输一般使用其它协议,比如 HTTP 来实现,如果实在无法避免用 XMMP 协议传输文件等,它一般使用 Email 中常用的 base64编码。

但既然这样,为什么 Gtalk 支持语音聊天呢?这就要说到另一个协议,XMMP 的扩展协议 Jingle,这是一个还没有被 XMPP标准正式采纳的扩展,而 Gtalk 采用的 Jingle 协议和已提交的草案也有所不同。Jingle 协议使得 Gtalk 支持 p2p 的多媒体互动,比如语音聊天功能。

那既然有多媒体功能扩展,为什么 Gtalk 现在不支持视频聊天呢?我不相信 Google 的工程师没有尝试添加视频聊天功能,可能的原因我猜想是视频聊天的性能达不到。猜想的依据是什么呢?Gtalk API 文档,Google 说:In the future, we plan to support SIP signaling as well. 如果 Jingle 能完美支持视频聊天,大概没有需要去支持另外一个类似的多媒体协议吧。

所以呢,我们可以看到虽然 Gtalk 的当前版本有内存泄露 BUG,而一年多来(2007年1月5日发布Gtalk 1.0.0.104) Google 仍然没有发布新版本,这说明 Gtalk 项目组的精力被其它更重要的东西占用了,这个东西会不会是对 Gtalk 视频和群组聊天的支持呢?我们拭目以待。

喜欢玩新软件的朋友可以尝试一下这个:Google Talk Labs Edition,里面有一些好玩的新功能!

重要评论:作者可能对xmpp还不是很了解,文章有很多的臆想,有些不太对。xmpp协议是个总称,它包括核心协议,扩展协议等(xep)等,事实上核心协议只规定了很小很基本的一些功能,大量的功能都是在xep中规定的。而xep在逐步完善中,其中的很多功能处于实验阶段,google可能是嫌麻烦,每一次协议更新都要修改软件,索性等协议功能稳定了再去实现。xmpp协议里面是有群组聊天的,叫muc,但google只实现了它的一个子集,叫 groupchat,而没有完整实现muc。视频聊天和音频聊天本质上是一样的。google可能就是再等xep中关于jingle部分协议的稳定以后再实现。而你看到的这句话:“In the future, we plan to support SIP signaling as well.”在google talk刚推出的时候就已有了。而且那个时候它还说会推出各个操作系统平台的版本。而如今呢?所以事情的发展是会变化的。还有google那时候说要支持 sip,并不是xmpp功能有什么问题,而是想使im用户能够统一起来,互联互通。因为sip和xmpp都是被ietf接受的标准协议。

Feedburner and Feedsky 的点击统计

我发现我真傻。

由于文章的原始链接被 Feedburner 修改,而 Feedburner 的子域名被封,以前一直无法从 Google Reader 里点击文章标题进入我的博客网站,我也一直以为这是件没办法的事情。今天无意中看别人的文章才发现,这是因为在 Feedburner 中启用了 Item link clicks 功能的缘故,我郁闷啊!

所以今天我把 Feedburner 和 FeedSky 的文章点击统计功能都关闭了,啊哈,链接干净了!现在总算可以直接点击订阅的文章标题进入我的博客文章页面了!