loading …

Archive

Posts Tagged ‘技术’

收到O’REILLY寄来的礼物

十二月 21st, 2009 edikud 3 Comments/320 hits

      今晚回宿舍的时候在楼下被楼管叫住,说有我的信件,拿到手一看,竟然是O'REILLY寄来的。里面是一本颇精美的记事本^_^,放图:

091221A004

      现在才相信O'REILLY的书后面都有的那张小明信片不是用来骗小孩的,确实可以寄回去换礼物,我今晚收到的这份礼物应该得益于《AI for Game Developer》那本书后面的明信片(我在半年前抱着试试看的心态将其寄了回去)。

      最近对O'REILLY出版的书都特别有爱,特别是在实习的时候经常翻阅的那本《Perl语言入门(第四版)》的复印本(没办法,该版书已绝版,我只能从图书馆借出来复印)。呵呵,话说今年购买或复印的O'REILLY图书也有5、6本了,而每本书的内容质量至少都能算是中上水平。O'REILLY这家出版商,就如它对自身的简介那样,具有浓厚的计算机专业背景,也因此形成了一个非常不同于其他出版商的出版方针——紧密地与计算机业界联系,出版市场上真正需要的计算机图书。它的编辑团队成员都是程序员或顶尖级技术专家出身,同时具有许多由相关领域的技术专家、咨询专家组成的固定作者群体。而阅读O'REILLY出版的图书确实有一种“直入主题”的感觉,能找到自己真正需要的信息,协助解决自己所关注的问题。

    现在顺便推荐几本O'REILLY出版的书:

  1. 刚刚提到的《Perl语言入门(第四版)》,也就是俗称的“小骆驼书”,该版的中文版由O'REILLY Taiwan公司翻译的,翻译水平相当的赞,内容更是经典,除了可以用它来快速学习Perl语言之外(同时记得自己多动手去实践),也可以作为一本Perl的小字典,如果忘了Perl的一些知识点可以用来速查。(PS:现在该书的第五版中文版可以在卓越网买到,但换了译者,我没读过,不好评论)

     

  2. 《集体智慧编程》 ,这是一本实战性较强的书籍,它通过将一些机器学习与人工智能的理论知识(公式)结合实际的例子生动地转化为一行行python代码,将智能分析的实际应用在读者面前展开,几乎称得上“手把手教你玩机器学习”。机器学习、模式分类等理论作为Web2.0的智能基石之一,它让长尾理论渗透于互联网的各个角落,Amazon豆瓣就是很经典的例子。这本书就是这方面应用的绝佳入门书(因为它确实比《模式分类》这种类教科书有趣多了)。

     

  3. 《代码之美》,这本书就不用我多说了,里面的大部分代码都很经典,皆出于大牛之手。它重复了一个观点:漂亮的代码真的可以让人窒息,写代码也是一种艺术!

     

  4. 《学习vi编辑器(第六版)》,vi作为Unix下面的标配文本编辑器,它有多重要我就不用说了。这本书可以推荐给vi或vim的初学者,毕竟这个强大的编辑器的使用方式确实太诡异了。(该书已绝版,华工北校区图书馆有得借,如果E文不错,也可以选择购买《学习vi和vim编辑器(影印版)》

     

  5. 《sed与awk(第二版)》,sed与awk这两个工具之于那些在Unix/Linux的Shell命令行下工作的系统工程师,就如同计算器之于会计,所以这本书是推荐给有志于从事Unix/Linux系统工程师这个行当的同学滴。(该书与前一本书一样杯具地绝版了,华工北校区图书馆有得借)

     

Perl通过Telnet远程执行命令

十一月 3rd, 2009 edikud 0 Comments/501 hits

      Perl脚本在远程的机器上执行命令的方法有几种,例如直接通过system函数调用rsh、通过NET::SSH:Perl模块通过ssh登录远程机器来执行或者是通过NET::Telnet模块通过telnet登录到远程机器上执行。笔者比较喜欢Telnet登录这种方法,因为它比rsh强大,却又足够灵活,既能达到SSH的使用水平,同时又足够轻巧(只需要一个模块:Telnet.pm就够了)。

      NET::Telnet模块的详细使用指南可以参考该模块的CPAN官方文档。我们在这里只简单地结合代码来介绍其使用方法。

01 use Net::Telnet;
02
03 my $t = new Net::Telnet(Timeout => 30,Prompt => '/[\$#>]/', Errmode => "return");
04 $t -> max_buffer_length("10485760");
05
06 my $ok = $t->open("192.168.1.12");
07
08 unless($ok eq 1){
09          my $errmsg = $t->errmsg();
10          print STDERR "$errmsg\n";
11 }
12
13 $ok = $t->login($username,$passwd);
14
15 unless($ok eq 1){
16          my $errmsg = $t->errmsg();
17          print STDERR "$errmsg\n";
18 }
19
20 my @temp = $t->cmd(String => "PS1=\"@@@\"",Prompt => '/@@@/'); #change the Prompt temporality
21 $t->buffer_empty;
22
23 while(my $cmd=<>){         #Exec each cmd in the cmds list
24         my @results = $t->cmd(String => $2, Prompt  => '/@@@/');
25         print $results[-1];
26         $t->buffer_empty;
27 }

 

     现在我们来对以上的代码进行解释,其中第3行就是建立一个telnet对象,其构造参数用于指定给对象所建立的连接将用到的参数,在这里我们指定了超时时间Timeout、错误模式Errmode,以及远程机器上的命令提示符Prompt。Timeout指的是Telnet登录或者执行命令的超时时限,我们这里赋予了30,也就是说如果远程机器在30秒内没有回显出命令提示符,telnet的连接就等于超时断开;Errmode有两种值:die和return,默认是die,如果选择的是die,则该对象所执行的方法出了错误,整个perl脚本就die掉并会把错误信息输出到标准输出中,如果选择的是return,则在出错的时候会直接返回一个undefined的标量值或一个空向量,并将错误信息放在对象中,可以通过对象的errmsg()方法来获取;Prompt这个参数很重要,因为NET::Telnet模块是通过命令提示符来判断登录成功与否以及命令是否执行结束,通过正则表达式来设定,我们这里设定为 "/[\$#>]/”,也就是说远程机器的命令提示符包含了’$’、’#’、’>’这三种字符之一,如果设定的命令提示符不与该正则表达式match,那么在登录或者执行命令的时候,会因为等不到命令提示符而超时。

      在第4行,我们更改了这个Telnet对象的缓冲区,单位是K字节,该缓冲区是用来存放远程机器上的输出结果的,这里的10485760也就是10MB(绝对够用的啦)。

      第6行,通过传入远程机器的IP地址调用Telnet对象的open方法来连接远程机器,如果连接成功,则返回值等于1。在第13行,通过用户名和密码登录到远程机器的系统中。

     在第20行,我们通过Telnet对象的cmd方法将要在远程机器上运行的命令传递到远程机器上面去。这里我们通过向远程机器传递PS1=“@@@”这条命令临时地改变了远程机器的命令提示符,之所以这样做,是因为Telnet模块是根据命令提示符来判断传上去的命令是否执行完毕的,如果我们传上去的命令中包含了可以与Telnet对象的Prompt参数match的字符串,那么cmd方法会直接返回(好囧啊)。于是乎,我们在这里临时改变了其命令提示符为@@@(应该不会有一个变态的命令会用到这种字符串吧)。由于命令提示符改变了,因此我们在cmd方法中还要传入Prompt参数@@@,否则下场就如同Telnet对象的Prompt属性没设对…。

     第21行,清空Telnet对象的缓冲区,否则有可能出现命令输出错位,这个读者可以自己试一下是怎样的效果。

      23行至27行,就是重复地读取命令,再将命令放到远程机器上执行,之后将结果输出。记得执行这些命令的时候要使用新的命令提示符作为分割点哦,也不要忘了在获取返回结果之后清空缓冲区哈。

Perl中处理“跨多天”时间的一点小技巧

九月 14th, 2009 edikud 0 Comments/147 hits

      这段时间在用perl写一个处理log的脚本,需要在文本中截取出以特定格式描述的时间点,之后根据时间点判断是否在某个duration内。

      由于时间的记数周期不一,例如月份的周期,所以,如果要按照年月日时分秒这样来算,是颇痛苦的,我们可以直接将其做一个转化,转成纪元秒,也就是UNIX世界中的一个统一个时间单位,之后再以秒为单位进行计算,最后再转回人类所使用的格式。

      在这里,我们先读取到以文本描述的时间,提取各个时间单位,从秒到年,存入变量中,之后转化为纪元秒(epoch second):

1 $begin_epoch = timelocal(0,
2                          $begin_mm,
3                          $begin_hh,
4                          $begin_day,
5                          $begin_month-1,
6                          $begin_year);

 

      在这里,将秒、分、时、天、月、年几个参数传入timelocal这个函数,该函数会返回相应的纪元秒。值得注意的是,参数中的月份是从0~11,这是和C函数库一致的,而$begin_month这个变量依然是用1~12月来表示,所以这里要减去1。timelocal这个函数在Time::Local这个模块里面。

      还有一个地方需要注意:

      1. 如果年份参数大于999,该参数就直接表示年份;

      2. 如果参数的大小介于100~999之间,就代表是1900年的一个offset,也就是说112指向的是2012年;

      3. 如果参数值介于0~99,就比较奇妙了,其英文描述是:“interpreted as shorthand for years in the rolling ‘current century,’ defined as 50 years on either side of the current year.”,在1999年,这个参数如果是0,代表的就是2000年,这个参数是55,就代表1955年,但是在2019年的时候,55代表2055年。

     接下来可以对这个纪元秒进行处理,例如,加上D天,H个小时,M分钟可以用这样来表达:

     $end_epoch = $begin_epoch+$D*24*3600+$H*3600+$M*60;

 

     这样的话,$end_epoch就代表了D天H个小时M分钟后的纪元秒,可以将其分解为人类常用的表示格式。用的就是localtime这个函数了,这个是perl的标准库的函数,不需要额外引入模块。用法也很简单:

     @end_time = localtime($begin_epoch);

 

     那么在end_time这个列表里面,就按顺序就包含了秒,分,时,日,月,年,星期几,年中的第几天,通过下面的代码可以形象的描述:

     ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);

 

     要注意的就是,这里的月份范围依然是0~11。

使用GAE的memcache实现Session

四月 3rd, 2009 edikud 4 Comments/383 hits

        之前一直在寻找Google App Engine自带的WEB框架里面用来记录Session的API,但是除了一个没有什么用的webapp.RequestHandler.request.cookie之外,似乎没有类似功能的接口,可能GAE将该玩意忽略了,所以只好使用别的方法来解决Session信息的记录。

        后来选择了使用GAE的memcache来解决这个问题,直接把所有需要记下来的session信息写入到memcache中,至于使用什么东西来标识不同的session,我选择了用户的IP:webapp.RequestHandler.request.remote_addr。

        现在来一个例子:

1 if not memcache.get(self.request.remote_addr+"count"):
2        nv = count()          
3        memcache.set(self.request.remote_addr,nv,120)
4 else:
5        nv = memcache.get(self.request.remote_addr+"count")

 

        这段代码可以实现一个简单的访问计数,nv这个变量用来记录该用户的访问序号,count()函数用来将访问数增加1。第一行代码用来获取memcache中关于该用户的IP的访问数,而要在用户IP地址的基础所加上字符串count就是用来区别其他session信息的标识,也就是说count是本session中访问数的标识值。所以,用户IP和字符串count组成的字符串就是该session的用户访问数在memcache中的的标识值。

        如果在memcache中没有该用户的访问序号信息,就调用count()函数,之后将访问序号记入memcache中(第三行代码),所调用的memcache.set函数的第三个参数就是该数据的过期时间,这里使用的是120,代表数据在120秒之后就过期,这个期限可以按实际需要调整,过期机制使我们不用花精力来删除过期的session数据。

        这种实现方式和普通的session最大不同的地方在于,传统的session对象的生存周期是从访问开始到访问结束,而本实现的session数据的生存周期在于我们设置的过期时间(在某种程度上,这样是不科学的,因为我们不知道用户的会话会持续多久)。而且,在本实现中,不同的session之间不是分割的,我们还可以获取其他访问对话的session数据(只要知道对方的IP就可以获取),而传统的session之间是互相独立的。

当飞信的API遇上GAE的URL Fetch API

三月 23rd, 2009 edikud 5 Comments/1137 hits

      这几天一直在想怎么使用GAE来实现一个自动短信通知功能,由于google的免费短信服务已经关闭,而飞信的python库又不怎么可能放到GAE上面。最后找到了这玩意:http://sms.api.bz/ 它是中国移动飞信的一个第三方的API入口(不能保证安全性和私密性),通过GET方式发送请求就可以实现发送飞信的功能。

      具体的url如下:

http://sms.api.bz/fetion.php?username=13800138000&password=123456&sendto=13800123001&message=Hello

      其中username的值是发送方的手机号,password是发送方的飞信密码,sendto要发送目标的手机号码,而message就是飞信中的内容。上面的那个URL就是用来向13800123001内容为”Hello”的飞信,要注意的是,发送方和接收方必须是飞信好友。

      有了这玩意,配合一下GAE的URL Fetch API,就可以实现自动飞信通知的功能:

1 from google.appengine.api import urlfetch
2
3 def sendmessage(number,message):
4     url="http://sms.api.bz/fetion.php?username=13800138000&password=123456"
5     url=url+"&sendto="+number+"&message="+message
6     urlfetch.fetch(url, payload=None,
7                    method=urlfetch.GET,
8                    headers={},allow_truncated=False,
9                    follow_redirects=False)

 

      要发送飞信的时候,就通过调用sendmessage这个函数就行了,number是指目标的手机号,而message是要发送的内容。

(原创文章,转载请注明原文链接:http://www.javayu.com?p=2489)

使用pojo实现enum

三月 20th, 2009 edikud 3 Comments/235 hits

      enum是java1.5的新特性,可以实现在C/C++中的枚举功能,但是这种特性要JDK1.5才有,对于一些要使用JDK1.5以下的的JDK版本进行开发的项目 来说就不得不寻求其他的方案了。

      之前我做的项目要在JDK1.3的虚拟机上面运行,而我用的JDK是1.6的版本,所以在最终整合的时候出现了一些问题,后来经师兄指点,结合网上的资料,利用java本身最 础的类特性(pojo)实现了enum。

      举个例子,下面先来看一段 enum 的代码:

         enum Color{

                red,blue,yellow,black,white;

         } 

       声明了一个含有五个枚举量的枚举Color,这是在JDK1.3下面是运行不了的,我们给他来个重构:

          class Color{

                  public static final Color red = new Color(0);

                  public static final Color blue = new Color(1);

                  public static final Color yellow = new Color(2);

                  public static final Color black = new Color(3);

                  public static final Color white = new Color(4);

                  int value ;

                  private Color(int value){
                          this.value = value;
                  } 

                  public int getValue(){
                          return this.value;
                  }

          }

      经过这样的改造,两种Color其实已经在使用上有很强的兼容性了,至少在java中的类C形式的代码中,实现了行为的一致。无论Color是使用enum还是class定义,我们都可以使用下面的代码:

          Color r = Color.red;

          Color b = Color.blue;

          Color color = Color.red;

          if(r != b){......}

          if(color == b){......}

    我在JDK1.5下面编写的代码经过这样的重构,就可以在JDK1.5下面运行了。

程序设计心得

三月 17th, 2009 edikud 6 Comments/237 hits

      我高一的时候开始学习编程,到现在已经有了五年多的编程经验,回忆起数年来对程序设计的学习和研究,总会有新的发现和体会。

      记得在最初接触编程的时候,和大多数人一样,对程序设计充满着陌生和好奇的感觉,每写出一个程序就会有很大的满足感。之后再进一步深入地学下去,有些人就会觉得困难成倍地增加,其中很多人选择了放弃,究其原因,我认为不是什么有没有恒心的问题,而是思想观念上的一种不适应。 

      在开始的时候,很多人都会在编程语言上下苦功,本身并没有错,但是有些人就会产生程序设计的问题就是对编程语言的使用问题的观念,导致他们在进一步学习程序设计的过程中忽略了各种编程思想的吸收和运用,例如有些人很清楚指针的工作原理,却不懂得怎样去利用指针构造并操作完美的链表,他们设计出来的链表也许在删除节点的时候没有释放内存,或许在插入节点的时候因赋值顺序错误导致链表“断裂”,信息丢失,等等。随着要解决的问题复杂度越来越大,没有经过良好程序设计思想组织起来的代码会出现各种各样的逻辑错误,这种漏洞百出的程序在运行时有时甚至会导致系统崩溃。 

    所以在对编程语言有了初步了解之后,应该开始重视编程思想的培养,语言很重要,但究竟只是工具,思想才是精髓。当初我得到戴泽贤老师借予的《数据结构》一书后,就通过阅读书中的各种数据结构及相应算法的代码来吸收书中的思想。我认为学习数据结构最能培养一个人对解决程序设计问题的敏感性,其建模思想对解决各种棘手问题有很大帮助,看书的时候要学会思考,例如循环队列的尾节点为何一定要是空的。当你懂得程序设计问题是类似于数学建模的思想问题后,你才算是真正入门了。这时,面对程序设计,才不会无所适从。

    再进一步提高自己,就要靠做题来验证各种算法思想,前期做题的时候要参考别人的代码,学会从执行效率上分辨出代码的优劣,其次再讨论其实现难度。之后就是形成自己的风格,有自己的一套解题方式和相应的算法,例如在快排和堆排的具体使用上,能有自己的一套运用方式。根据具体问题采取自己所熟悉的相应算法来解决,这样的话或许程序的运行效率不是最高效的,但解决问题的速度会比较快,而且这种根据自己风格设计的程序出错率通常会比较低。这在平时的应用开发上会体现一定的优势,更不用说是在分秒必争的编程比赛上了。当然,程序的执行效率也很重要,它是算法优劣的体现,必须要通过更多地做题,来总结经验,每做一道题,就会加深对某种算法思想的理解,进而改进自己的编程风格,我最初的时候喜欢用深度优先搜索(DFS)来解决迷宫问题,后来发现其实宽度优先搜索(BFS)更好,特别在解决最短出路上更有效,而DFS适合于解决窄路径迷宫寻找有效路径问题。 

     总之做题真的很重要,给个例子,今年的华工软件学院闯入ACM/ICPC世界总决赛的队伍的四名队员人均做题量上千。中大的ACM训练每星期有周赛,每个月有月赛,是使中大的ACM编程氛围保持活力的主要原因,也是中大代表队可以成为ACM总决赛常客的重要因素。所以今年软件学院也开始搞半月赛了。So~对于参加编程比赛的人来说,平时所累积的代码量决定了他的比赛成绩。

STL std::string functions

三月 17th, 2009 edikud 3 Comments/252 hits

      之前玩ACM和TopCoder的时候一直要用到C++的stl::string,还是挺好用的(虽然比不上java的String),现在将它的函数统一列出来作为备忘:

begin                     得到指向字符串开头的Iterator  
end                        得到指向字符串结尾的Iterator  
rbegin                    得到指向反向字符串开头的Iterator  
rend                       得到指向反向字符串结尾的Iterator  
size                        得到字符串的大小  
length                    和size函数功能相同  
max_size               字符串可能的最大大小  
capacity                 在不重新分配内存的情况下,字符串可能的大小  
empty                    判断是否为空  
operator[]              取第几个元素,相当于数组  
c_str                       取得C风格的const char* 字符串  
data                       取得字符串内容地址  
operator=               赋值操作符  
reserve                   预留空间  
swap                       交换函数  
insert                      插入字符  
append                   追加字符  
push_back              追加字符  
operator+=              += 操作符  
erase                      删除字符串  
clear                       空字符容器中所有内容  
resize                     重新分配空间  
assign                    和赋值操作符一样  
replace                   替代  
copy                       字符串到空间  
find                         查找  
rfind                         反向查找  
find_first_of             查找包含子串中的任何字符,返回第一个位置  
find_first_not_of     查找不包含子串中的任何字符,返回第一个位置  
find_last_of             查找包含子串中的任何字符,返回最后一个位置  
find_last_not_of      查找不包含子串中的任何字符,返回最后一个位置  
substr                     得到字串  
compare                 较字符串  
operator+               字符串链接  
operator==             断是否相等  
operator!=              判断是否不等于  
operator<               判断是否小于  
operator>>            从输入流中读入字符串  
operator<<            字符串写入输出流  
getline                    从输入流中读入一行

[ZT] Linux Kernel 交互图

三月 17th, 2009 edikud 0 Comments/159 hits

      一张来自www.makelinux.net的图片,用直观的方式让您自上而下了解整个内核的情况,你可以看到最重要的层次,功能,模块,功能和要求,并可以放大和拖动,每个项目还都有相应的源代码和文件链接,非常棒!

点击访问:Interactive map of Linux kernel

LKM

 

原文来自:www.cnbeta.com

帮老爸做网站

三月 16th, 2009 edikud 0 Comments/49 hits

      记得过年前就答应过我父亲说要帮他的公司做一个信息发布网站,用来发布他们公司的班车信息和订票信息。当时主要是考虑到他们公司的竞争对手已经抢先一步在googel map上标注了地址信息,所以就打算用GAE做一个订票站点。

      昨晚奋斗到凌晨,第一次尝试不用DW来构造页面,从python代码到HTML到CSS都是在eclipse上完成的,现在发布了第一个版本,只能用来发布订票电话等信息,除了一个统计访问人数的递增器之外,几乎不含有业务逻辑计算。

      上午在淘宝花了10RMB买了一个.info域名,打算和那个应用绑定在一起,结果自己不小心把用该domain申请的Google Apps删了,再使用哪个这个domain注册Google Apps要多等5天才行~囧~只好继续用appspot的二级域名来访问:

      gzrpcc.appspot.com

      这个星期争取抽时间把班车信息发布给做出来才行,之后再研究一下怎么做好自助订票的功能~~不知道能不能在上面挂google广告呢~