2007年9月28日星期五

第一节课

今天刚上完在美国的第一节课,Programming Languages。主讲的 Prof. Flanagan 是一个很年轻的教授,语速很快,我觉得我最多听懂了六成的内容。课的内容并不是对某几个语言进行解释剖析,而是概观地对编程语言的历史,特点,要求等等进行介绍和讨论。一个很大的不同是,当每个同学介绍自己喜欢的语言时,很多人更倾向于Perl, Python, Ruby这些脚本语言,这些在国内基本上是十分生僻的。Prof. Flanagan则很喜欢Java。

我这学期的TA也要求会一点Perl, 所以还是要花功夫在这些原先不熟悉的脚本语言上。

研究生的生活比想象的要累啊。

2007年9月19日星期三

The first 4 days in USA

I'm using the computer in the Library of UCSC to write down this article. Since there is no Chinese Input Method, I can just only use English. Sorry.

I was a terrible journey flying to America. Due to some "Mechanic Problem", the flight from Chengdu to Beijing was delayed, for about 3 hours. Therefore, I did not catch the original flight from Beijing to San Francisco. After 5 hours terrible waiting, I finally got on an airplane flying to Los Angeles. 11 hours on plane, no deep sleep, I had been very tired. Entering the Custom and Border Protection was straight. 1 hour later, I flew from Los Angeles to San Francisco. When I got there, it was 10:00 pm, PST. Fortunately, Peggy Pollard, a member of ISI(International Student Inc.) came to the airport and pickup to Santa Cruz. It was very kind of her!

I was living with four Chinese exchange students temporarily. We got along with each other very friendly. They told me lots of things here, about housing, banking, campus, calling plan, yard-sale, etc.. Yesterday, I settled down in a house near the beach of Santa Cruz, which was a wonderful place to live, full furniture, $560 rental per month, plus month to month payment. I do not hope better.

Santa Cruz is a small town, with about 56000 population, mediterranean climate, friendly people. There is no crowd of people, and all town is quiet. Santa Cruz means "Holy Cross", which is famous for the beach and surfing here. Everybody should like it. By the way, bus transportation is powerful in Santa Cruz.

The campus is wonderful, too, since it is sitting on a hill and in a forest. More properly, I should say, UCSC is just a part of the Mt. Santa Cruz, because the natural environment here is well preserved. You can see deers eating grass, and squirrels are fighting for nuts. Inside of the forest, the temperature is very low, but the air is even more fresh. I can say, I like here.

There can be lots of things to tell, but I must stop here. I think my oral English is growing better and better everyday.

:)

2007年9月2日星期日

最近的情况

最近逐渐熟悉了Colemak键位,打字速度开始恢复了。确实,世上无难事,只怕有心人。

关于RecycleTorrent,我完成了应有的基本功能,已经把代码传到了SourceForge。SourceForge上RecycleTorrent项目的地址是http://sourceforge.net/projects/recycletorrent/。同时,编译后的程序可以在我的Windows Live SkyDrive上下载(运行需要安装最新的Visual C++ 2005 Redistributable Package)。对BitTorrent感兴趣的开发者可以试试。

另外,最近打算将RecycleTorrent扩展成P2P下载平台。具体细节我还在考虑。

2007年8月23日星期四

尝试Colemak布局



Colemak(http://colemak.com/)键盘布局是我在比较Dvorak键盘布局的效率时认识的。Colemak给我的第一印象是,它跟QWERTY很像,ZXCVBQW这些键的位置都没有变。在Colemak网站的FAQ(http://colemak.com/FAQ)上,发明者Shai Coleman列举的Colemak优于其他键盘布局地方有(括号内是我的解释):


  • Colemak的用户群正在增加。(有助于不断完善Colemak,开发相应软件。)

  • Colemak的设计初衷之一就是易学,很容易从QWERTY转换过来。(Colemak指改变了17个按键,而Dvorak改变了33个按键)

  • Colemak保持了Ctrl+Z/X/C/V四个快捷键的位置(请参见我的文章《解决Dvorak键盘布局快捷键的问题》)

  • Colemak对小指的负担不高。(Dvorak把L放在右上角。L键是一个常用键,因此对右手小指要求较高)

  • Colemak键盘布局的设计很稳定。(不会经常变化,要求用户重新熟悉)

  • Colemak可以在多种操作系统上使用。(Windows, Mac, Linux/Unix)

  • Colemak有相应的打字练习。(http://colemak.com/Learn


对于在Windows下使用中文输入法的用户来说,安装Colemak布局的最好方式是注册表重映射(Registry remapping)。注册表重映射是在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout键下建立一个名为Scancode Map的二进制键值,用于存放新键盘布局的键盘扫描码(Scan code)。启动系统时,Windows读取修改后扫描码,这样,整个键盘就被重映射了。如果想改回QWERTY布局,只需要删除键值,重启即可。

为什么是最好方式呢?因为一般输入法都有自己的键盘映射模块,会自己判断扫描码。注册表重映射是很低层的修改,新键位对输入法同样有效。

Colemak的注册表重映射实现在这里下载:http://colemak.com/pub/windows/Kmapper-1.0.zip。其他实现方式在这里下载:http:http://colemak.com/Download

用Colemak打了这两篇文章后,感觉最不舒服的是J键。虽然J在英文里是极罕见字母,在拼音里确是常用字母。但愿习惯后会好些。

解决Dvorak键盘布局快捷键的问题

虽然Dvorak键盘布局比QWERTY的排列更合理,但对于已经习惯QWERTY键盘的人来说,迁移的难度是很大的。对于惯用右手握鼠标的人来说,其中之一便是左手的那些热键,Ctrl+Z, Ctrl+X, Ctrl+C, Ctrl+V, 等等。因为现在的ZXCV都在键盘偏左的位置,所以不得不用右边的Ctrl键;另外,ZXCV等键相隔都很远,按起来很不舒服。

有没有办法修改Windows的全局热键呢?当然不行,我们没有Windows的代码。

能否使用重映射(Remapping)按键将ZXCV等键映射到原来的位置呢(这种方法很常见,很多日本同人格斗游戏的按键都可以通过软件修改到WASD来)?不行,因为这样就破坏了Dvorak键盘布局。

我们要找的是这样的工具,它能全局地拦截按键,并对指定的按键进行替换。替换的要求不只是单独的按键,同时要是按键序列。替换后的按键同样不只是单独的按键,同时要是可自定义的按键序列。

我尝试了很多软件,都无法满足以上的所有要求。昨天下午,无意间在VeryCD的一篇帖子里找到一个名叫Key Transformation(http://www.softboy.net/key/)的软件,试用后发现它满足所有要求。不过这是一个收费软件($44.95!)。要知道,别人一套虚拟机(Parallels Workstation)也才$49.99啊,怎么说,虚拟机的含金量也要高得多吧。放弃……

终于,在RandyRants找到了一篇文章介绍AutoHotKey(http://www.autohotkey.com/)。这是一个开源软件,免费。它能读取脚本文件,按宏的定义来替换按键。由于AutoHotKey支持的宏命令非常丰富,所以它完全能够胜任我们的要求。

比如,我们创建一个脚本文件test.ahk,输入

^j:: SendInput ^c

运行脚本后,按下Ctrl+J就相当于按下了Ctrl+C,而Dvorak的J键就在QWERTY的C键的位置。

当然,我们完全可以用AutoHotKey来模拟出一整套Dvorak键盘布局。事实上,在AutoHotKey的论坛上已经有人写出了脚本(http://www.autohotkey.com/forum/topic4473.html)。

另外,如果有兴趣的话,可以到这里(http://www.siteuri.ro/dvorak/)看看。这里有一个程序,你输入了一段文字后,它可以输出用各种不同键盘布局输入的效率比较。48小时之内允许测试5次。注意,最后一个键盘布局是Colemak,我正在熟悉它。关于Colemak键盘布局,我在下一篇文章中详细介绍。

不过,用新键盘来打出这么多字真是很累啊。万事开头难。

2007年8月20日星期一

RecycleTorrent 能够正常工作了!

经过近半年的努力,现在终于把一个有界面、有逻辑的基本BitTorrent客户端做出来了!主要还是用了Qt的框架,在Visual Studio 2005 SP1上编译。中间遇到很多问题,在解决问题的过程中也学到了不少,得到很多乐趣,这也是激励我在计算机这个行业中不断前进的动力了。

当然,目前连一个Alpha都还说不上,因为功能很不完全。不过既然已经走上正规,后面的工作主要就是体力活了:)

放上几张截图:


初始状态


尝试连接中


和BitComet对传数据


断开连接后

------------------------------------------------------------

当我把程序复制到一个干净的Windows XP SP2虚拟机里时,居然报错,截图如下:



Dependency Walker出错如下:



Side-by-Side?没怎么听说过啊?其实就是%systemroot%下面那个WinSxS文件夹里面装的文件。那些动态链接库按版本存放在WinSxS里。生成程序的时候,VS会创建.manifest文件,该文件用于保存目标文件的外部依赖的库,同时记录库的版本。当库文件未找到或者版本不符时都会提示程序无法运行。因为虚拟机里当然没有安装VS2005 SP1对应的CRT库,所以报错。下载Mircosoft网站上的Visual C++ Redistributable并不能解决问题,因为Microsoft目前还没有更新到SP1版本。当我复制[Visual Studio 2005 安装目录]\SDK\v2.0\BootStrapper\Packages\vcredist_x86\vcredist_x86.exe到虚拟机并安装后,就没有问题了。Microsoft的东西还真是挺麻烦的。(主要参考了这篇文章:Side-by-side screwup

2007年7月30日星期一

在维基百科上发表了我的第一篇条目——瓦尔哈

源起我前两天在听瓦尔哈演奏的巴赫管风琴全集。应为是暑假回家来第一次听,确实很受感动,突然想去看看维基上关于瓦尔哈的条目是怎么描述他的。谁知中文维基上居然没有瓦尔哈的条目,英文的也写得很简略(维基上演奏家们的条目都相对较少,虽然他们可写的东西并不少)。

我想,听了瓦尔哈那么多的演奏,都没有为他做点什么,正好可以借这个机会报答一下。虽然我手上关于瓦尔哈的资料并不多,但网络本身就可以提供大量信息。于是花了两三天时间,把网上搜集到的资料收集整理后翻译成中文,加上图片,就成为了一个条目了。

维基是自由的网络百科全书,希望任何爱好音乐的朋友都来参与。如果我写的有什么不对的地方,请大家修改。

条目地址为:http://zh.wikipedia.org/wiki/%E8%B5%AB%E5%B0%94%E7%A9%86%E7%89%B9%C2%B7%E7%93%A6%E5%B0%94%E5%93%88

在国内由GFW无法直接连接维基百科。但因为Blogspot也是被封站点,所以既然您能看到这篇文章,那您可以使用相同的办法办法访问维基百科(条目应该没有敏感字词)。

2007年7月26日星期四

写了一个Firefox的扩展

实在受不了GFW的横行霸道。凭什么要把Wikipedia、Google Cache这些站点封了呢?现在就连上这个Blog都得用代理了,哎……于是,我在ErrorZilla Mod的基础上加上了对失败地址使用Web代理进行访问的功能。

插件名叫ErrorZilla Plus。下载安装后,每次遇到无法打开的地址,一个新的失败页面就显示出来。和ErrorZilla Mod不同的是,现在多了一个"Proxify"的按钮,其下增加了一个列表框。列表框里保存了几个Web代理的名字。用户可以在这几个代理中选择一个,用它对失败的页面进行访问。这样,每次打开维基中文出错后,只需要点一下Proxify就可以访问了。

目前初版是0.3版。在这个版本里,我是把代理列表直接保存在netError.xhtml里的,因为我实在找不到如何在Firefox里读取外部文件的方法,即使是XML也不行。还要请高手指点一下。

如果要修改代理的列表,请打开ErrorZilla Plus安装的目录(<当前profile目录>/extensions/{03651b2d-eb7d-4be7-af1b-dc0cd162dd54}),找到Content文件夹下的netError.xhtml。在该文件中部有一段标签的内容。代理列表在这里以XML的格式保存。name节点保存代理站的名字,website节点保存站点的地址,address保存查询页面的相对地址。更改了列表后请重新启动Firefox。

ErrorZilla Plus的下载地址是https://addons.mozilla.org/en-US/firefox/addon/5398,目前还在沙盒(Sandbox)中。

--------------------

又查了一些资料。Mozilla在扩展的Javascript里有执行权限的限制。向about:这样的地址的权限较低,因此无法调用外部文件。我试了一下XPCOM组件,直接打开about:neterror时,执行Components.class会提示“Uncaught exception: Permission denied to get property UnnamedClass.class”,而通过Chrome(打开chrome://errorzillaplus/content/neterror.xhtml)则没有问题。我想这个问题暂时没法解决,除非Mozilla修改它的权限策略。

2007年7月19日星期四

Singleton (单件) 设计模式

[2007.04.01]

最近在苏州一家计算机公司工作。因为大量用到了Singleton模式,而原来自己实现的Singleton模式存在内存泄漏的问题,所以花了点时间研究如何更好地实现Singleton模式。

我原来实现的Singleton模式是这样的:

(Singleton1.h)

class Singleton
{
public:
static Singleton* Instance()
{
if (_instance == 0)
_instance = new Singleton;

return _instance;
}

private:
Singleton() { _testPtr = new int; }
~Singleton() { delete _testPtr; }
static Singleton* _instance;

int* _testPtr;
};


(Singleton1.cpp)

Singleton* Singleton::_instance = 0;


很明显,Singleton::_instance 只是一个指针,在程序结束的时候并不会被自动析构,因此Singleton::~Singleton() 也不会被调用,完全是一个空壳。为了使Singleton类被自动析构,一个最直接的办法就是把Singleton::_instance改成类的实例而非指针,这样静态变量_instance就会在程序结束的时候自动被析构,再设法让_instance中的析构函数调用Singleton类的析构函数,就可以解决内存泄漏的问题了。

这里有三种解决方案:
1. _instance是一个和Singleton类不相关的类(假设为SingletonDestroyer)的实例;2. _instance是Singleton类的父类的实例;3. _instance是Singleton类自己的实例。

第一种解决方案首先被排除,因为如何让SingletonDestroyer访问Singleton类的析构函数是一个问题。Singleton类可以是任何不同的类,有不同的接口,无法统一地被SingletonDestroyer处理。当然,可以让所有的Singleton类继承于一个基类,使它们具有相同的接口,再在SingletonDestroyer中保留一个此基类的指针,在SingletonDestroyer::~SingletonDestroyer()中调用基类指针的析构函数( _singleton->~Singleton(); ),但这样其实已经退化成第二种解决方案了,所以第一种解决方案被排除。

让我们来看看第二种解决方案的实现。

(Singleton2.h)

class Singleton
{
public:
Singleton() { _singleton = 0; }
~Singleton()
{
if (_singleton != 0)
{
_singleton->Destroy();
delete _singleton;
}
}

Singleton* _singleton;

protected:
virtual void Destroy() {}
};

class Sub : public Singleton
{
public:
static Sub* Instance()
{
if (_instance._singleton == 0)
_instance._singleton = new Sub;

return (Sub*)_instance._singleton;
}

private:
Sub() { _testPtr = new int; }
void Destroy() { delete _testPtr; }
static Singleton _instance;

int* _testPtr;
};


(Singleton2.cpp)

Singleton Sub::_instance = Singleton();


Sub是实际的单件类,所有Sub类都继承于Singleton类。Sub::_instance是一个Singleton类的对象,在程序结束时会被自动析构,调用Singleton::~Singleton()。Singleton类的Destroy()是提供给子类销毁自己的成员数据的,会在Singleton::~Singleton()中调用。如果子类不覆盖Destroy(),则不执行任何程序。

这个解决方案在非MFC的单线程程序中可以正常工作,但是在多线程的MFC程序中有问题(运行到afxmem.cpp的某行会出错),其他情况我没有测试。在我这里这个解决方案也被否决了。

第三种解决方案:

(singleton3.h)

class Singleton
{
public:
static Singleton* Instance() { return &_instance; }
void Setup(int intValue) { *_testPtr = intValue; }

private:
Singleton() { _testPtr = new int; }
~Singleton() { delete _testPtr; }
static Singleton _instance;

int* _testPtr;
};


(singleton3.cpp)

Singleton Singleton::_instance = Singleton();


还是第三种方案最简单。Singleton::_instance是自己类的实例,由于是静态成员,所以可以存在。程序结束时,自动调用自己类的析构函数。在MFC和非MFC、单线程和多线程中都没有问题,可以参考。
4.23更新:如果Singleton类是继承于一个父类BaseClass,那么它的_instance变量的类型和实例化都应该不变,而不是像指针那样,BaseClass* _instance; _instance = new Singleton;

另外还有一个第三种方法的变种,就是使用智能指针std::auto_ptr,代码如下:

(Singleton4.h)

#include <memory>

class Singleton
{
public:
static Singleton* Instance() { return _instance.get(); }
~Singleton() { delete _testPtr; }
void Setup(int intValue) { *_testPtr = intValue; }

private:
Singleton() { _testPtr = new int; }
static auto_ptr<singleton> _instance;

int* _testPtr;
};

(Singleton4.cpp)

auto_ptr<singleton> Singleton::_instance(new Singleton);


[2007.07.19 更新]

其实既然Singleton的生存周期贯穿整个程序,那么必然只有在程序结束的时候才会析构Singleton类。既然程序都结束了,操作系统也会自动回收所有相关内存,那么Singleton类的析构就显得多余了。

因此,又写了一个Singleton的模板类,更方便一点了:

(Singleton5.h)

template <typename T>
class Singleton
{
static T* _instance;

Singleton() {};

public:
static T* Instance()
{
if (_instance == NULL)
_instance = new T;

return _instance;
}
};

(Singleton5.cpp)

template <typename T>
T* Singleton<T>::_instance = NULL;

注意,Singleton的相关实现也要放到头文件里。使用时,所有类继承于Singleton,并传入类自己作为模板参数。如果子类希望有private的构造函数,则还需要让自己和Singleton类成为友元,因为Singleton里有new T,会访问子类的构造函数,而并没有什么修饰符可以指定只允许父类访问,而不许其他对象访问。

如:

class Sub : public Singleton<Sub>
{
friend class Singleton<Sub>;
Sub();

public:
int testFunc() { return 0; }
};

main()
{
Sub::Instance()->testFunc();
}

总结一下。某些类一个程序执行期间只需要存在一个副本。通常这种类仅仅提供某些功能,不存储任何数据,或者仅存储程序的全局数据。对于前者,只需要将类的所有函数设为静态函数即可。对于后者,则使用单件模式。一个类由普通类转换成单件类不需要做任何修改,只需要添加_instance成员变量和Instance()成员函数。

2007年7月18日星期三

解决 Ubuntu 中的循环依赖 (Cycle Dependency)

最近在VMware中安装了一个Ubuntu系统。由于创建系统时没有要求安装虚拟网卡,因此需要安装Ubuntu的软件包时,需要自己下载deb文件,拖进系统,然后双击调用gdebi进行安装。可是,当我尝试安装G++时却出现了问题:g++-4.1这个包依赖libstdc++6-4.1-dev这个包(也就是C++库),而libstdc++6-4.1-dev又依赖g++-4.1。结果两个包都装不上。





上网搜索,在Ubuntu官方论坛找到了解决方法:

在命令行下执行以下语句
sudo dpkg -i --ignore-depends=libstdc++6-4.1-dev g++-4.1_4.1.2-0ubuntu4_i386.deb
sudo dpkg -i --ignore-depends=g++-4.1 libstdc++6-4.1-dev_4.1.2-0ubuntu4_i386.deb
即可。
(g++-4.1默认安装包名为g++-4.1_4.1.2-0ubuntu4_i386.deb;libstdc++6-4.1-dev默认安装包名为libstdc++6-4.1-dev_4.1.2-0ubuntu4_i386.deb)

也就是说,强行让两个安装包忽略依赖项。

使用apt-get自动安装应该没有这种问题。

2007年5月22日星期二

一点关于宗教和信仰的讨论

昨天朋友过来,就和他讨论了一下最近在重新看的《卡拉马佐夫兄弟》。仍然还是从宗教大法官开始。为什么阿廖沙要叫道“你的长诗是对耶稣的赞颂,而不是诋毁……”呢?大法官难道不是在告诉耶稣,也告诉所有的读者,耶稣所做的其实并没有起到他希望的效果,他是高估了普通人类吗?难道他没有指出,与其跟随耶稣,整日在旷野里嚼草根、禁欲,魔鬼的食物、奇迹更能吸引他们吗?而宗教大法官剥夺了人民的自由,却给了他们食物,他充当的是魔鬼的,而非基督的代言人,虽然他告诉人民他是暂时代替基督来统治他们的。问题就在这儿:基督教之所以可以成为最大的宗教教派之一,离不开它对政治统治提供的无可取代的帮助。不可否认,如果基督教仅仅是一门宗教,它不可能得到如此庞大,如此久远的发展的。统治者们利用基督教实施他们的统治,即使他们自己本来毫无宗教信仰,他们而得在民众面前装得很虔诚。相反,基督教在民众心中是很纯洁的。从它被创造之初到现在,宗教本身没有,也不可能有很大的改变。在基督教传播的过程中,变化的只是谁利用它,怎样利用它,它的本质则始终如一。

当然,时代变化了,民众也会变化。从中世纪的神权统治,到重视精神思想的文艺复兴,再到现在的重视物质的社会,民众对宗教的态度也会有很大的变化。基督教在现在之所以还会有这么大范围的影响,应该要归功于它在这么多世纪以来的积累。设想一下现在有一门全新的宗教被创造出来(注意,是宗教,而不是法轮功那种迷信),有可能产生像基督教那样的影响吗?基督教强调灵魂不死,强调忏悔和救赎,这在一千年前完全可以成为人们寄托希望的容器,但在现在,金钱往往是人们最首要考虑的因素。

期待下一个精神时代的到来。

毕业设计——BitTorrent客户端(二)

最近把程序的极原始的雏形写出来了。现在的进度是:
1) 连接Tracker。获得正确回应后记录返回的IP列表,等待回应中指定的时长后重新连接。返回错误回应则记录错误信息。连接错误和回应错误则等待预先设置的时长再重新连接。使用一个线程作为定时器,检查每个Socket是否到了应该重连的时间。

2) 连接Peer。主动连接或者被动接受连接。Tracker获得IP列表后,会把列表存放到一个IP池里。由另一线程去定时尝试连接那些IP。任务一开始会开一个Socket来监听某个指定端口,当有人尝试连接本客户端,则接受连接。

3) 消息流程还是按照BT规范里约定的。主动发起者先发送握手消息,被动接受者收到握手消息后,检查无误,发送回应握手消息,连接建立。然后双方发送Bitfield消息,然后Unchoke消息等等。不同客户端对Bitfield消息的产生方式不一样。像BitComet就是严格按照规范里描述的,把所有Piece的消息写到一个Bitfield里去,而uTorrent对大任务是把Bitfield消息置空,而用Have消息通知Peer它有哪些Piece。

我在自己计算机上测试的,下载可以达到2MB/s的速度。瓶颈是在消息处理流程过长,以及主动请求频率的问题。

4) 保存和恢复任务进度。我是参考uTorrent的方法,将任务信息用bencodin写到文件里去。

5) 文件读写缓冲。所有写文件的操作先是写到内存里去。当缓冲区达到指定大小时,将缓冲区数据写入文件。读操作时,先到缓冲区里去找,若没有则读实际文件。当然要解决的问题是,如果程序意外终止,缓冲区里的数据来不及写到文件里去,那下载的数据就白费了。还是要研究一下Windows关于文件缓冲的技术。

6) 为了简化代码,目前暂时是把支持多任务给去掉了的,不过以后是肯定要加入的。因为每个回收站文件也是一个另一种类型的任务,纯上传任务。

以前使用的是同步Socket,但是问题很多:每个Peer连接都要开启一个线程,要有地方来管理这些线程。另外要控制某个Peer连接去主动请求Piece也很难,因为是要由一个线程去控制另一个线程。线程与线程的同步也是要解决的问题。总之,同步Socket是不能采用的方案。

现在所有连接使用CAsyncSocket,MFC框架。异步Socket + 消息驱动可以保证很少的线程,很低的CPU占用,很高的速度。当然,异步Socket也要解决一些“异步”相关的问题,比如消息发送的先后问题。

关于回收站模式,我会在下一篇文章中介绍。

2007年5月15日星期二

找到 Skype 的官方代理

前段时间用 Skype 3.1 版的时候发现在 Connection 选项卡里面多出来一个“CERNET Beta”,应该是TOM通过某种技术或者手段让教育网用户也能连上美国的服务器。这两天换了3.2版,发现CERNET Beta没有了,但代理设置里面是有值的,用密码显示器得到用户名和密码后一试,竟然可以直接在浏览器里面使用,看来是得到了一个极品的适合教育网使用的代理了。当然也不知道能坚持多久。需要的朋友可以试试:

IP:59.64.114.29
端口:2000
用户名:skype
密码:tomskype

2007年5月5日星期六

大学生在小学

一天做梦,梦见我和中学的几位同学不知道什么原因被要求去小学重读一年的书。可以选择任何一所小学,任何一个年级,任何一个班。当然,在现实中这样的事就太匪夷所思了,要求一个拥有大学生知识和经历的人像一个小学生那样生活一年。不过假如用小说来写出一部这个题材的作品,估计会是挺有趣的吧:

想想,首先,选哪一个年级?六年级会比较接近一点,不会像一年级那样无聊吧。平时上课干什么呢?总不能老打瞌睡吧,那不就白白浪费了一年的时间了。做自己的事,看自己的书?那要假设老师和学校强制要求认真听课。怎么和那些小学生交流呢?总不能一年时间都一个人太孤僻吧。既然那些老师都能和这些小孩打成一片,那我们也能做得到的。作业和考试?当然是轻松完成了。作息安排上,当然是不能迟到、早退的。星期一升国旗的时候肯定会比较醒目吧,这么一个个儿……

当然还有很多情况了,不过小说的结尾是什么呢?一句疑问:“不过,我干嘛要到这儿来上一年小学?”可能最大的好处就是能够有一年时间拥有良好的作息规律,对身体好吧:)

重读《穷人》

五一这几天又在重读陀氏的《穷人》,虽然是他的第一部小说,当也写得确实很真切。除了好奇为什么那个时代的俄罗斯,富人和穷人的差异有如此之大外,我想起了我妈妈。

和马卡尔·杰武什金一样,我妈妈也是一个在岗位上辛辛苦苦、勤勤恳恳了一辈子的人,虽然在机关里是出了名的好人,好心肠,品德高尚,但也从来没有过工作上的升迁。同马卡尔一样,每个月都还是按时拿到虽然不算微薄,但还能过得去的薪水。虽然不多,但她也从来不抱怨什么,总还是认为单位对她已经很不错了。当然,她的这种满足对她来说是好事,事实上,在这个竞争激烈的时代,她在工作方面拥有的能力也确实只配拿到那么多薪水。从我的角度来说,我一直纳闷,干嘛就不发发奋,好好学点技术含量高的知识,争取到金字塔的更高层去呢?依她的人缘,这并不是很难办得到的啊?

现在我逐渐想到,当一个人还年轻的时候,他总是可以对未来充满希望,认为即使现在的状况再差,他也有时间、有力量去改变。而当一个人在一个环境里面呆上了10年、20年以后,他就很难再有改变现状的希望和勇气了。应该改变的东西早就应该已经改变了,没有变化过的东西也基本上不可能在现在再来改变了。即使现状再怎么差,看来都是命运决定了的,自己的力量已不足以撼动它了。不管这种思想如何如何,在那种境况下的人应该是很容易产生这种想法的。君不见这位马卡尔·杰武什金,在他“年纪轻轻”的时候也是那么富有热情,发疯似的去追求女演员,现在老了,每天都用同样的衣装,走同样的路线,到同样的地方,做同样的工作,和同样的人打交道,得到同样的回应。我不清楚我妈妈年轻时具体是怎么想的,不过现在,她是肯定不会再去想怎么让自己升迁,获得更多的报酬。

当然,支撑杰武什金活下去的,是瓦尔瓦拉,支撑我妈妈活下去的,是我。正如瓦尔瓦拉写到的,“您倒想想看,您吃尽了苦头,直到现在,您还只是为我而活着,为我的欢乐而欢乐,悲伤而悲伤,为我的情意而活着。”因为瓦尔瓦拉还年轻,还有希望,所以瓦尔瓦拉很有可能改变她的现状,变得好起来,比他能够设想到的更好。既然他以她的欢乐而欢乐,那么瓦尔瓦拉的改变也就意味着他自己的改变,这是他活下去、极端无私地帮助瓦尔瓦拉的根本原因。同样,我妈妈也只能把希望寄托在我身上(这是她的一句口头禅),希望我的未来会比他的好,这样她也就能心满意足了。

当然,我们的处境比杰武什金他们好,我也比瓦尔瓦拉更有力量去改变自己的命运。

2007年4月24日星期二

毕业设计——BitTorrent客户端(一)

从苏州回来以后还是一直在写自己的毕业设计。题目是我自己选的,做一个BitTorrent客户端,并且在这个基本的客户端上加入我自己设想的独特功能,使这个客户端更加强大。从研究的角度讲,我认为这个题目还是比较合适的,对我个人来说,实现BitTorrent客户端绝对是一个合适的挑战;对计算机领域来说,如果我设想的独特功能被证明是有意义的,那也是有价值的。

当然,要实现“独特功能”,首先得把那个基本的、能够和现有别的客户端通讯的底层做出来,而这个才是难点所在。想一想,虽然一篇BitTorrent协议不算长(和IA-32、FAT这些比的话),但需要实现的东西还是挺多的:

按照协议的顺序,首先要实现bendcoding的解析器,这个在解析torrent文件和解析tracker服务器响应时都会用到。除了解析,还要提供接口,让外部访问者能获得结构化了的数据。

其次,要能和tracker服务器通讯。要充分考虑到tracker可能发生的各种情况,如连接失败,需要重定向,返回无效数据,返回错误,以及返回理想信息等。做到后面还要考虑多线程向多个tracker服务器发送请求,维持请求间隔时间,使用代理服务器访问等等。

再次,要能和各个peer通讯,传输数据。这部分其实就是在博弈,在你我都不知道对方规则的情况下各自制定一套规则,规则本身是由协议里面定义的消息元素来构造的,但是具体细节完全是由你我自己控制的。然后大家在一个对等的平台上,通过规则进行通讯,双方的目的都是在不违反对方规则的同时使自己获得最大的收益。比如,我可以一次向某个peer发送很多请求,但如果这个peer很忙,他就有可能choke我,一个可能更好的策略是,分散请求面,首先请求最稀少的数据块。自己获得最大利益并不意味着要损害对方,最好的结局是双赢,所有人都最终得到完整的数据。当然除了博弈这个算法的问题外,还有很多基础的网络问题要解决。

最后,还要把各个模块整合起来。比如在向tracker服务器发送请求时就要提供当前任务已经下载和上传了多少数据量。而这个数据量显然是要在和peer通讯时统计得到的。类与类之间肯定需要一个中间层来联系。像这种耦合在程序里实在不少,因此架构设计也是需要非常谨慎的。

原本打算还要把图形界面加上,做成一个完整的可发布软件,现在看起来一是时间不够,我实在是找不到能在短时间内实现像uTorrent那样界面的GUI解决方案,二是觉得作为毕业设计,界面确实不是最重要的,不能喧宾夺主嘛。所以界面的事可能得先缓一缓了。

下一篇里我会介绍一些我客户端的框架和一些实现细节,也算是为论文先打个草稿啦。

2007年4月15日星期日

Dvorak 键盘布局

突然对Dvorak键盘布局感兴趣了,想尝试一下这种比我们传统QWERTY布局更高效得多的打字方式。不管Dvorak是否对中文拼音输入有没有帮助,至少它应该可以提高我写代码、写注释的速度吧。



加上了这种布局后,刚开始确实很别扭,马上发现了两点问题:第一个,切换到搜狗拼音后,键位仍然是QWERTY的,这个应该是搜狗内置了键位的。不知道那种拼音输入法支持Dvorak。第二个,原来Ctrl+C, Ctrl+V的复制粘贴,现在变成了原来的Ctrl+I, Ctrl+.,这就不是习不习惯的问题了,因为一般都是右手握鼠标,左手进行这些键盘的快捷操作。用左手输Ctrl+I和Ctrl+.很痛苦啊。不知道Windows有没有机制可以保持这些快捷操作的键位不变。

下载了一个免费的打字练习软件KP Typing Tutor,开始慢慢练习。听说,原来的QWERTY打字者转到Dvorak键位后,一般能在一个月之内恢复原有打字速度,所有还是挺有信心学好Dvorak的 :)

另有一篇介绍Dvorak键位的文章,有兴趣的可以看看。

2007年4月1日星期日

我的留学美国申请经验(二)——Resume

准备材料。对于CS来说,申请材料一般就是个人陈述(Personal Statement,简称PS)和简历(Resume 或 CV)。这两个材料都非常重要,不是可以一蹴而就的,写的时候要多听取别人的意见,多修改。

先从简单一些的Resume开始吧。Resume之所以相对简单,是因为他的格式和内容相对固定,和PS相比,就像GRE的Argument和Issue一样。Resume的页面可以参考网上和同学之间关于求职简历的经验,但从内容上说毕竟还是会有不同。另外,并不是每个学校都要求提供Resume。

尽量把Resume控制在2页A4纸内。

以下是我的Resume的格式,大家参考吧:

1) 基本信息 (Personal Information)

包括姓名,性别,出生日期,e-Mail,国籍,联系地址和电话,最后还可以用一句话来简单描述一下自己打算申请的研究方向。

1. 关于姓名,一定要是名在前,姓在后。

2. e-Mail要写上以后会用来申请学校的邮箱,我用的是Gmail,很不错,从没有发生过寄丢邮件或者错误归到垃圾邮件的问题。

3. 联系地址当然是按地方的从小到大顺序写下来,包括国内邮编和国家。

4. 关于电话,固定电话的话可以使用 “+国码-地区码-电话号码” 的格式:对于中国,国码是86;地区码前面的0省略,如010只写10。举个例子,+86-10-12345678。移动电话可以使用 “+国码-4-3-4” 的格式,如 +86-1301-234-5678 。当然,这些格式只是我的推荐,不是硬性规定。

2) 教育背景 (Education and Qualification)

1. 本科信息包括就读学校和主修专业,开始和结束时间,所获学位,相关GPA和Ranking。对于一般还未毕业的申请者来说,应该在本科结束时间和所获学位前加上 Expected。GPA可以包括综合GPA和专业GPA,可以写上4.0分制和100分制。关于GPA我后面还会在Online Application里解释。原则是,如果某个不是必需的分数、排名对自己不利,情愿忽略掉也不要强求。

2. 中学信息可以写上去,注意学历信息要按就读的先后顺序从后往前写。不过中学以前的学历就不要写了。

3. TOEFL,TWE,GRE成绩及考试时间。可以注明TOEFL和GRE的类型,是iBT还是PBT,General还是Subject,后面写上分数。TOEFL可以只写总分,GRE最好写明每一类的分数,百分比。

4. 如果自己有业余爱好,或者在校的辅修等等和申请专业比较相关,也可以简单提及,格式和本科主修专业类似。

3) 奖项,荣誉 (Reward and Honor)

按照获得时间从后往前写。太小、太久的奖项都不要写,那些不重要。相反,和申请专业相关的奖项则很重要。一般来说,就写上大学时期的和专业比较相关的就行了。获奖证书不要寄到学校去,他们不认识中文的。

4) 专业能力 (Professional Skill)

简单描述一下自己在欲申请专业的相关能力。比如我是申请计算机的,所以就写上自己熟悉的语言,曾参与过项目中自己独立编写的代码行数等等。

5) 项目经验,研究经验 (Major Projects and Research Experience)

对每一个值得提及的、和申请专业相关的项目、实际经验进行简要描述。仍然是按照发生时间的先后顺序从后往前排。这部分一般是Resume的主要部分,能体现申请者的竞争力。

拿计算机来说,我的每一个项目有以下几个大点:
1. 概述该项目,主要能解决什么问题;2. 基于什么技术,一些出彩的技术细节;3. 有什么前瞻性的意义,自己的哪方面能力在项目中有所体现。

我认为,介绍项目最重要的不是项目本身怎么样,而是你自己怎么样。老美们当然不大会对你的项目感兴趣,他们更感兴趣的是你这个人怎么样,因此,如何通过介绍项目间接地来介绍自己才是这部分最需要考虑的。因为各个专业、项目细节都不一样,所以请各位自己仔细斟酌如何写好这部分吧。

6) 课外活动,社会实践 (Extracurricular Activities)

介绍一些和申请方向相关的课外活动,让教授们更全面地了解你。美国人都还是非常看重每个人的社会经验、人际关系这些的,这个地方就是展示自己一个小舞台。当然,不要写得太琐碎,捡重要的写,扼要地写,关键还是突出这些事情对自己在申请方向上的影响。对了,还是建议按事件发生的时间从后往前写。

大家可以参考一下我写的Resume。写得不算好,但大家去其糟粕,取其精华吧。:)

相关链接:

GPA 计算器 "GPA Wizard": http://offer.go3.icpcn.com/main/main.htm

My Resume: http://www.puzatech.com/kerenjin/

一些免费下载乐谱的网站

2008.12.19 更新:有些网站死掉了,更新一下列表。
2007.4.1 更新:偶然的机会找到了一个乐谱网站,竟提供 J.S. Bach 几乎所有乐谱的免费下载,不敢私藏,拿出来和广大巴赫爱好者共享。此网站除提供巴赫乐谱下载外,还提供 Mozart 部分的乐谱下载。
http://www.tobis-notenarchiv.de/ : Tobi's Notenarchiv。极好。提供 J.S. Bach 几乎所有乐谱的免费下载。midi 和 cap。cap 文件需用 capella 系列的软件打开。capella 的相关信息可以在 http://www.capella.de/ 找到。


昨天无意间找到一片帖子,上面列举了很多免费乐谱下载的网站,我把其中比较适合喜欢古典音乐的和有乐器特长的人的选了出来,写在下面,供爱乐者们借鉴。midi 格式的文件请用 Cakewalk 等软件打开。

格式:URL : 网站名。我的评价。介绍。乐谱格式。(备注。)

1) http://www.classicalarchives.com/main/ : Classical Music Archives。极好。提供几乎所有著名音乐家的著名作品,数量极多。midi。需免费注册或支付注册。

2) http://www.lysator.liu.se/~tuben/scores/ : Free Sheetmusic from Johan Tufvesson。好。主要提供早期音乐家的作品。pdf。

3) http://www.dlib.indiana.edu/variations/scores/ : VARIATIONS Prototype: Online Musical Scores。好。美国印第安纳大学图书馆提供的乐谱下载。网上浏览,当然你也可以下载到本地。

4) http://imslp.org/wiki/Main_Page:International Music Score Library Project。最好。这是一个收集了几乎你能想到的所有古典音乐家的乐谱的维基式网站,非赢利性质。这应该是目前最正规、最全、最稳定的乐谱资源网站了。它的维基介绍:http://en.wikipedia.org/wiki/International_Music_Score_Library_Project。pdf。

5) http://www.piano.ru/inter-e.html : Piano.ru。极好。一个俄国网站,提供了非常多音乐家的钢琴作品乐谱,只不过作品名都是俄文,看起来比较费劲。pdf。

6) http://www.sheetmusicarchive.net/ : Sheet Music Archive。好。收录了很多音乐家的著名作品,只是作品数量稍嫌少。pdf。

7) http://www.recmusic.org/lieder/:The Lied and Art Song Texts Page。很好。这里提供了非常多的歌词资料,康塔塔,歌剧,晚祷等等都有,有原文,也有各种翻译。不过此网站似乎很注重作曲家的数量,每个作曲家的作品都不是很全。不过考虑到其非赢利性质,已经很不错了。html。

8) http://www.tobis-notenarchiv.de/:Tobi´s Notenarchiv。极好。上文已有介绍。midi 和 cap。

9) http://icking-music-archive.org/scores/ : Werner Icking Music Archive。好。Werner Icking Music Archive 网站作品列表,音乐家数量多,作品也多,比较推荐。格式杂。

另外再介绍两个下载 SoundFont 的网站。这里提供的都是 SF2 格式,没有创新声卡的朋友可能需要自己转换一下。

1) http://hammersound.net/cgi-bin/soundlink.pl

2) http://www.homemusician.net/soundfonts.php

如果大家有什么好的音乐资源,欢迎大家一起交流分享。

2007年3月14日星期三

我的留学美国申请经验(一)——选校

年初的时候一直在忙计算机研究生留美的申请,现在学校也在陆陆续续地发回结果了。虽然我了解计算机科学(Computer Science,以下简称CS)的申请细节,但是因为申请完全是我自己操作的,所以自认为还是在这方面可能有一些经验感想可以拿出来分享一下,希望也能对其他专业打算出国留学的朋友有用。

因为是留学美国,申请CS研究生,所以TOEFL和GRE这两个考试是基本上都必需的。GRE Subject很麻烦,虽然所有大学的网站上都是说不是必须,强烈推荐,我还是没有去考。我建议有条件有时间的朋友可以考,没条件的不必勉强。我的TOEFL是2005年11月考的,GRE是2006年6月,考的都是旧试。新试我不太了解,不敢乱说。G、T的复习方法我就不班门弄斧了,希望大家都能考出理想的成绩。

在开始准备申请材料前,首先得把我们希望申请的学校选出来。如果很多论坛、资料上所说的,选学校确实是最花时间的一步,即使是把学校排名定在前150,没有1、2个月也是很难得到满意的结果的。我选学校的方法是,按照USNews统计的最新综合排名和CS专业排名,在前150名内安排名先后将每一个学校CS专业的每一个导师情况看一次,将该导师的情况简单地记录在一个文档内,方便以后回顾。按该导师的研究方向、兴趣和我自己的研究兴趣的相关程度为该导师评一个分,这样,每审阅完一个学校,这个学校的总分也就基本出来了,自己对每个学校也就有了一个自己的评价。同时,因为一般CS专业都会有很多不同的研究小组,我也会看看有没有适合自己的研究组,如果有,当然这个学校更适合选择。(可以发现,一般的规律是,排名越靠前的学校,其研究领域和研究小组的多样性越大,当然申请的难度也越大)

大致看完每个学校后,我筛选出30-40个学校,在参考了这些学校奖学金发放情况、招收国际学生比例和它们的申请难度、公私立、学费、所处地域、甚至学校网站的人性化设计(^_^)等等因素后留下了10多个打算申请的学校名单。由于考虑到CS申请人数多,竞争大,我建议学校数量最好不要少于10个。关于奖学金等方面的排名,可以去太傻和寄托上搜帖。

因为我是通过网络申请的(现在很多学校都不提供纸申了,网申更方便),所以我强烈建议现在用Excel做一张表,用来记录每个学校的信息和申请情况。表可以有以下内容:学校名(Institution Name),申请专业的页面(Department Page),申请截止日期(Application Deadline),网申页面(Online Application Page),网申帐号(Application ID)以及申请情况页面(Status Page)。当然也可以再加入综合排名、专业排名这些内容,让这个表一看就可以一目了然。然后按照申请截止日期先后将学校排序,找到我们最紧迫要申请的学校。接下来就要开始准备申请材料了。


相关链接

USNews: http://www.usnews.com/usnews/edu/college/rankings/brief/t1natudoc_brief.php

太傻论坛:http://bbs.taisha.org/index.php

寄托论坛:http://bbs.gter.net/bbs/index.php

心情很郁闷

很久没来写过东西了。本来那段时间忙申请学校,就有一段时间没来,越不来就越不想来。人就是这样……

今天晚上心情很不好,闷得慌。一来最近忙的毕业设计感觉进展比较困难。二来觉得自己还是很自闭,很少朋友,自己又不愿去结交。还是老问题,总觉得别人都认为我是一个怪人,和大家不是同类,自然而然是被大家排除在外面的。计算机和网络确实提供了绝缘的社交平台,可以让任何人在任何时候重塑自己。但是我知道网络不是生活的全部啊。我不希望自己是一个十足的“御宅族”。

我努力工作,努力学习,我能期望什么呢?我自认为自己懂得很多东西,但是没人知道这些,没人认同这些,这样连我自己都开始怀疑自己了。我猜我以后能有一天变得比周围的人更有地位,更有财富,我需要认同和尊敬,但是我只把个人能力考虑进去了。要获得我想要的,除了个人能力还需要很多其他的资本,人际关系,商业头脑,等等,更何况我的个人能力又能有多强呢?

我不相信有任何女人会喜欢我,我也不想去追求哪个女人,虽然我希望获得别人的爱,但是我还是认为所有的女人都会认为我是一个异类,一个不值得信赖的人。是的,因为我总认为自己是一个没有任何地位的人,连一般的普通人都不如。平时强装笑颜,其实内心里面是虚的。因此我非常强烈地希望证明我自己的价值。

当然,我知道,每个人并不是那样想的。每个人的处事方式都不一样,只是我的这种在我的周围比较少罢了。就像一个围城,里面的人想出来,外面的人想进去。有男女朋友的人当然也有他们的苦衷,有很多朋友和人际关系的人当然也有他们的麻烦。但是社会就是这样,它会自动地同化异类,消除异类,而这些异类要不就妥协,要不就只有发疯了。

对于我来说,这种异类的生活何时才能结束呢?人都是可塑的,我并不认为我没有作为一个正常人资格。是我改变自己去妥协呢,还是等着自己的环境改变呢?我不知道。

每个人都是人,都具有人的情感,也有最为人都存在的缺陷。很多时候感到恼怒,感到嫉妒,虽然知道产生了这些感情证明自己小气,窝囊,也不想承认,但现在慢慢觉得,是一个正常人都不可避免会有不愉快的感情的,也就不再像小时候那样强烈地看不起自己。我可以原谅自己,可是如果别人知道了我的想法,不可避免地会引起别人的反感,我不想发生这样的事。很多时候也感到后悔,对不起那些关心着和关心过我的人,也为那些曾经误会过我的人感到遗憾,但是一切都过去了,道歉又能补救什么呢?我是害怕自己的道歉会引来白眼,还是真的认为没有必要呢?我不知道。我内心深处的有一面是胆小的,极怕受到伤害的,但我不认为我是胆小鬼,这是人人都有的,虽然大家一般都不会说出来。

EVA 第三话里的律子的一段话很好:“豪猪虽然想将自己的温暖传给对方,但身体靠得越近全身的刺越会使彼此受伤”,美里的回答“所谓长大成人就是不断散了又聚,聚了又散,为了让彼此不会受伤害而保持一个适当距离。”如果真的像庵野秀明所想的,人与人不再有“距离”了,这个世界会不会更好些呢?