老韩
17十一/090

搜狐技术俱乐部演讲

  上周五的事情,但今天才拿到片片。由于是公司比较高规格的技术交流会,所以准备了很长时间。尽管如此,在现场的时候,由于当时来的都是各技术部门的头,所以一开始难免有一点紧张,还好随着全身心的投入,最终顺利进行了下去,发挥还算是正常。
  介绍一下这个技术俱乐部:搜狐技术俱乐部成立于搜狐11周年之际,是在Charles的亲自倡导下,由各技术团队相关负责人组成的一个俱乐部。其旨在通过交流工作、研讨技术、分享成果,促进公司技术管理人员相互交流借鉴、增进各技术版块间彼此了解,从而更好地达到技术资源有效整合;通过对于最新的技术应用动态的集体研讨与集体学习,相互启迪、相互促进提升搜狐整体技术水平,从而更好地推进搜狐“技术产品驱动”战略。

  刚开始讲:

刚开始讲

  从远处看:

远处

  NO和Sogou的技术老大:

NO老大

  我们老大,帅吧?呵呵:

老大

  讲的是这个主题:

演讲主题

14十一/093

尝试Python For S60手机开发

  生活中,我们似乎总能碰到那么一群人:爱好新奇事物、敢于探索和研究、不计回报分享经验。通常,我们称这种人叫“奇客”或者“极客”,他们有一个英文专用名词叫“Geek”--如你所见,这个词已然脱离了它的原义,不再是贬义的“畸形人”或者“野人”,甚至是“傻瓜”、“呆子”,而是成了对大多数能熟练应用各种开发工具、对新鲜事物有着相当的敏感、热衷于分享以及对开源事业有着近乎虔诚信仰的牛人的尊称。IT圈子里,如果有人能够称你为“Geek”,那绝对是一种荣耀,且不管在你的思维里是骂人抑或是有意贬低。这种人我身边不少,典型的比如QYB同学以及Alvayang同学。这俩人爱好新事物已经到了近乎BT的地步。同时技术也的确高超,经常有事没事给我灌输一些闻之未闻的东西,比如前一段时间,这俩家伙在办公室拿着笔记本电脑玩起了乒乓球,羡煞我们,纠结半天原来是他们利用笔记本的硬盘保护技术原理,写了一个模拟自由落体的重力感应程序,籍此来欺骗我们幼小而纯洁的心灵。
  这里先交代这么一段,事实上和本文并没有太大的关系,写下来因为想说明,我之所以会去研究这么一些杂七杂八的东西,或多或少是受了他们的影响,事实上我对这些东西是不怎么感冒的,因为在我看来这些纯粹是过把瘾就歇菜的体验。虽说科学技术是第一生产力,但在我看来它还取决于两个前提:一是你研究的科学技术是否有实用价值,二是你研究的技术假设能转化成生产力,需要投入多大的成本。倘若仅仅是体验式的去玩,倒不如回家背几段唐诗宋词四书五经,兴许更能体悟到“死生契阔,富贵在天”的真理(这人怎么这么扯?这二者貌似没什么关系)。
  但还是得研究呀,为什么呢?首先一个是,倘若跟他们混在一起,不懂是要被鄙视的;其次,丫的这俩人长得太帅了,老子百试不爽的阿Q思维(长得帅的没有我程序写得好、程序写得好的没有我帅)在他们面前完全不起作用。尤其是QYB同学,据江湖传闻,这家伙初进SOHU的时候,被诸多甭管已婚未婚的姑娘们追着问:你结婚了没有?那意思基本上就等同于:想不想出轨?想出轨跟我来!而老夫在SOHU两年多,却从来没有收到过女同胞类似的关怀,煞是凄凉,只恨得仰天长叹:苍天无眼呀,我帅得这么具体居然会没人看上我!(有会拉二泉映月的吗?给我来一段,眼泪酝酿中。)

  倒,废话又有点多了,下面转入正题:

  一、准备工作。
  (一)硬件:
    1、没有蓝牙的请准备一根蓝牙棒,有蓝牙设备的请启用蓝牙设备。
    2、S60V3手机或PDA,有蓝牙支持。
  (二)软件:
  1、Python for s60V3。
  下载地址是:https://garage.maemo.org/projects/pys60/,目前最新版本是1.9.7,Python内核是:2.5.4。
  在这里要鄙视一下Nokia,文档更新太慢了,搞得老夫先是从Nokia官网上跑到了SourceForge,然后从SF.net上下载到一个文本文件,在文本文件里才找到最终的项目主页地址。
  2、putty
  目前最新的版本是0.6,支持Socket远程连接,可以直接通过蓝牙的COM端口连接到pys60的Console上去进行开发。关于这个,可以参考QYB同学之前的一篇文章:《尝试了一下 Python for S60》,当然他这篇文章有一个问题,就是讲得不够详细,从他文章下面的留言就可以看出,还是很多人不知道怎么用putty来连pys60的Console,所以在接下来的过程当中,我也会图文并茂地跟大家讲解如何连上去。因为在这个过程当中,我也是折腾了半天才弄清楚的。

  二、安装:
  安装的过程就比较简单了,首先是下载到Python for s60V3,下这个文件:

  这是一个tar.gz文件,Windows下可以用WinRAR打开,打开后会看到这样一个PyS60Dependencies文件夹:

  事实上只要安装三个文件就行了:

  其中:ssl_nokia_1_5_7.SIS,是ssl lib,可不安装,Python_1.9.7.sis是主文件,必须安装,PythonScriptShell_1.9.7_3_2.sis是Python在s60下的GUI程序,要通过它来启动Python。
  你可以用蓝牙将文件传到设备上安装,或者通过Nokia的套件来安装。无论如何,我们安装好了,试着跑两行代码,在我E71上的截图如下:

  三、尝试开发
  那么到这里,我们已经成功把Python安装到S60上去了,同时也能跑,那么接下来就试着从Windows上用Putty来连接手机上的Python Colsole,毕竟在手机上敲代码实在是件不靠谱的事情。在此之前我们需要说明一下,在我的Windows XP环境下,Bluetooth在连接S60之后,默认会把Outgoing的端口打开,而Incoming的端口是需要手工添加的,这一点与有些文章里所描述的不是一样,我不知道他们当时的环境是怎么样的,也许是基于1代Bluetooth的设备,安装驱动程序后会默认打开Incoming的COM端口吧,但是至少我这边是手工添加之后才能打开Incoming端口的。

  首先设置Bluetooth:
  在Bluetooth设备上点右键,然后选“打开Bluetooth设备”(如果快捷栏没有图标,请在控制面板里找,呃,怎么搞得像是菜鸟教程一样?呵呵),在打开的面板上,选择“COM端口”,点击下面的添加按钮,然后再在弹出的面板上再选择“传入(设备初始化连接)”,当然,这是默认的,直接点确定就可以了。这时候,我们会看到面板上多了一个传入的端口,我当前机器的这个端口在COM8上。

  这一步设置成功,就意味着蓝牙的Incomming端口已经初始化成功,此时就可以用Putty去连这个端口了。我们打开Putty,新建一个Session,将Connection type设置为:Serial,此时Serial line默认会填充为COM1,把COM1修改为COM8,将这个Session命名为:NokiaE71S60,先保存一下:

  然后我们双击打开刚才的那个Session,此时Putty的界面会停留在等待响应的阶段,那么这个时候我们要在手机上打开Python,通过选择菜单打开“Bluetooth console”,选择蓝牙所在的计算机。待确定之后,就可以看到Putty已经有了响应。切换到Python的开发界面上去了:

  好了,到现在为止,我们已经连接到手机的Python上去了,开始写一段代码吧,这是一段调用PyS60自带messaging信息库来发送短信的代码,我这里要发送一个字符串给我自己的手机:

  经过测试,可以很快收到自己发的短信。在开发的过程当中,还犯了一个错误,就是:把手机号码赋值到一个Int型变量上去了,结果提示错误,事实上手机号码应该是字符串的。
  好吧,接下来,就要考虑开发一些比较好玩的东西了。

分类: Python 3 评论
4十一/091

使用Flash Cookie技术在客户端永久保存HTTP Cookie

  前言:
  在我负责的一个项目中,为了实现一个特殊的需求,要求在客户端的Cookie中长久保存一份数据,但是我们知道在客户端Cookie里保存数据是不稳定的,因为用户可能随时会清除掉浏览器的Cookie,在这种情况下,一般的解决方案是重新向服务器端发送一个请求,以获得一个新的HTTP Cookie数据,并将其保存--就一般的交互需求而言,这是没有问题的。但是,倘若我的需求是:要求恢复到原来的Cookie里保存数据呢?呵呵,这种情况,倘若服务器端没有做特殊的处理的话,显然是很难实现的。在尝试了许多方法之后,我们最后选择使用FlashCookie技术来做。

  一、什么是Flash Cookie?
  下面我首先来介绍一下FlashCookie。
  FlashCookie是由FlashPlayer控制的客户端共享存储技术,它具备以下特点:1、类似HTTPCookie,FlashCookie利用SharedObject类实现本地存储信息,SharedObject类用于在用户计算机上读取和存储有限的数据量,共享对象提供永久贮存在用户计算机上的对象之间的实时数据共享;2、本地共享对象是作为一些单独的文件来存储的,它们的文件扩展名为.SOL。默认时,它们的尺寸为不超过100kB,并且不会过期——这一点与传统的HTTP Cookie不同(4KB);3、本地共享对象并不是基于浏览器的,所以普通的用户不容易删除它们。如果要删掉它们的话,首先要知道这些文件所在的具体位置。这使得本地共享对象能够长时间的保留在本地系统上。
  从上面可以看出,FlashCookie具有可操作性、比普通HTTPCookies有着更大存储空间、更好的隐蔽性等优点。加上现在FlashPlayer已经成为互联网用户标配之一,不存在兼容性的问题,因此它非常适合用来保护客户端数据、收集用户行为等。
  根据加利福尼亚大学伯克利分校(University of California, Berkeley)的一项调查表明,目前全球Top100的网站中,至少有54家在使用Flash Cookie技术在进行用户行为收集,有兴趣的同学可以看看这篇文章:《Top websites using Flash cookies to track user behavior

  二、使用Flash Cookie永久存储HTTP Cookie流程
  要实现Flash Cookie永远存储的功能,显然,首先要实现Flash Cookie与Http Cookie的互通,所以,在技术上使用JavaScript与ActionScript的来进行沟通显然是最好的选择,因为在这两种语言之间,除了语法上相近,从沟通上也有着完美的实现。下面我们来看看实现流程(如图所示):
  使用FlashCookies来永远保存HTTPCookies流程图

  三、ActionScript实现:
  在明确了实现流程之后,那么接下来就是具体的实现了,首先是基础建设,在Flash端,我们使用的是ActionScript3来编程,下面实现了一个基本的Flash Cookies存储的类,在接下来的过程当中,我们将通过这个类来实现对Flash Cookies的操作。当然,这里只是把流程以及关键的技术讲清楚,涉及到具体的操作,则需要您自己来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
 * Package laohan.flashcookie
 * Author:handaoliang
 * Create Date:2009.11.03
 * Last Mofied Date:2009.11.03
 * CopyRights:Handaoliang.com All Rights Reserved.
**/
package laohan.flashcookie {
    //注:由于我没有装Flex,所以只好使用Flash CS3来嵌入。
    //如果使用Flash Developer,则MovieClip这个包可以不包含。
    import flash.display.MovieClip;
    import flash.net.SharedObject;
    import flash.external.ExternalInterface;
 
    public class myFlashCookie extends MovieClip {//如果使用Flex,可以不继承这个类。
        private var cookieTimeOut:uint;
        private var cookieName:String;
        private var cookieSharedObj:SharedObject;
		private var currentCookie:Object;
        private var cookieValue:String;
 
        //构造函数。
        public function myFlashCookie(cName:String = "handaoliang", timeOut:uint=3600) {
            cookieName = cName;
            cookieTimeOut = timeOut;
            cookieSharedObj = SharedObject.getLocal(cName, "/" );	
		    if(isCookieExist(cName)){//如果FlashCookies存在。
		        currentCookie = getCookies(cName);
                //调用JavaScript里的jsSetCookies方法来设置HTTPCookie
                ExternalInterface.call("jsSetCookies",{fcookie:currentCookie});
                //trace(currentCookie);
		    }
        }
        //到期删除Cookies
        public function clearTimeOut():void {
            var obj:* = cookieSharedObj.data.cookie;
            if(obj == undefined){
                return;
            }
            for(var key in obj){
                if(obj[key] == undefined || obj[key].time == undefined || isTimeOut(obj[key].time)){
                    delete obj[key];
                }
            }
            cookieSharedObj.data.cookie = obj;
            cookieSharedObj.flush();
        }
        //添加Cookies( key-value )
        public function saveCookies(key:String, value:*):void {
            var today:Date = new Date();
            key = "key_"+key;
            value.time = today.getTime();
            if(cookieSharedObj.data.cookie == undefined){
                var obj:Object = {};
                obj[key] = value;
                cookieSharedObj.data.cookie = obj;
            }else{
                cookieSharedObj.data.cookie[key] = value;
            }
            cookieSharedObj.flush();
        }
        //删除当前Cookies
        public function removeCookies(key:String):void {
            if (isCookieExist(key)) {
                delete cookieSharedObj.data.cookie["key_" + key];
                cookieSharedObj.flush();
            }
        }
        //通过Key来获取Cookies值。
        public function getCookies(key:String):Object{
            return isCookieExist(key)?cookieSharedObj.data.cookie["key_"+key]:null;
        }
        //检查Cookies是否存在。
        public function isCookieExist(key:String):Boolean{
            key = "key_" + key;
            return cookieSharedObj.data.cookie != undefined && cookieSharedObj.data.cookie[key] != undefined;
        }
        //检查Cookies的到期时间
        private function isTimeOut(time:uint):Boolean {
            var today:Date = new Date();
            return time + cookieTimeOut * 1000 < today.getTime();
        }
        //取得Cookies的到期时间;
        public function getTimeOut():uint {
            return cookieTimeOut;
        }
        //取得Cookies名称。
        public function getName():String {
            return cookieName;
        }
        //清除所有的Cookies值。
        public function clearCookies():void {
            cookieSharedObj.clear();
        }
    }
}

  将所有的模块编译成SWF文件,我们将其命名为:hdl.swf,在上面的代码中,我们首先在构造函数里检查了Flash Cookie是否存在,如果存在,则会调用一个叫jsSetCookies的JavaScript方法来设置HTTP Cookie。那么,我们接下来要使用JavaScript来实现此SWF的调用以及互动。

  四、JavaScript的实现:
  1)首先要预定义一个供ActionScript3调用的方法,即上面说过的jsSetCookies方法。

1
2
3
4
5
6
7
//先定义一个全局变量
var flashCookiesValue = Null;
var jsSetCookies = function(flahCookieValue){
    var o = arguments[0];
    flashCookiesValue = o.fcookie;//在SWF执行时传递过来的值。
    document.cookie="handaoliang="+flashCookiesValue+";path=/;expires=Fri, 04-Dec-2009 08:44:07 GMT;domain=handaoliang.com";
};

  2)检查特定的HTTPCookies是否存在,如果不存在,则在页面上生成Object Dom节点,把hdl.swf加载进来。此时SWF会去检查Flash Cookies是否存在,如果存在,则去取得Flash Cookies,并且通过调用jsSetCookies来设置HTTP Cookies:

  1. if(document.cookie.indexOf("handaoliang=")<0){
  2.     //先去load hdl.swf,即在页面上生成Object对象:
  3.     var jsLoadFlash = function(){
  4.         var myFlashURL = "hdl.swf";
  5.         var myFlashObj = document.createElement("object");
  6.         myFlashObj.setAttribute("id","myFlash");
  7.         myFlashObj.setAttribute("classid","clsid:D27CDB6E-AE6D-11cf-96B8-444553540000");
  8.         myFlashObj.setAttribute("width",0);
  9.         myFlashObj.setAttribute("height",0);
  10.         var flahParamObj = document.createElement("param");
  11.         flahParamObj.setAttribute("name","movie");
  12.         flahParamObj.setAttribute("value",myFlashURL);
  13.  
  14.         var subMyFlashObj = document.createElement("object");
  15.         subMyFlashObj.setAttribute("type","application/x-shockwave-flash");
  16.         subMyFlashObj.setAttribute("data",myFlashURL);
  17.         subMyFlashObj.setAttribute("width",0);
  18.         subMyFlashObj.setAttribute("height",0);
  19.  
  20.         myFlashObj.appendChild(flahParamObj);
  21.         myFlashObj.appendChild(subMyFlashObj);
  22.  
  23.         var myDHTMLBody = document.body;
  24.         if(myDHTMLBody){
  25.             myDHTMLBody.appendChild(myFlashObj);
  26.         }
  27.     };
  28.     jsLoadFlash();
  29. }

  倘若Flash Cookies里也没有存储我们想要的数据呢?那么,此时就必须通过JS去请求特定的URL,然后使用JavaScript去调用AS3的方法来设置Flash Cookies吧。关于这一步,就由大家自己去实现吧。呵呵。

  五、结语:
  那么到这里,基本上就实现了使用Flash Cookies来永久保存客户端数据的全过程。最后顺便说一下就是,其实这种方式也只能用来对付非计算机专业人士,因为Flash Cookie本身也是可以删除的,一般情况下,flash cookie保存在系统的如下位置:C:\Documents and Settings\yourusername\Application Data\Macromedia\Flash Player\#SharedObjects\,如下图所示,一般情况下,在这个文件夹下可以看到很多的网站目录,里面有他们的Flash程序留下的痕迹:
Flash Cookies的保存位置
  当然,我这是删除过的,呵呵。

  --EOF--

3十一/090

从市场和产品的角度看搜狗云输入的应用

  中午吃饭的时候,在电梯里和搜狐小纸条的负责人聊起了搜狗昨天发布的云输入,然后我问他,有没有考虑在小纸条里嵌入云输入法?回答是没有,呃。
  事实上,在云输入法一发布的时候,我就在猜想搜狗会通过什么途径来推广。是延续一贯的众包方式?抑或是通过与第三方的合作?再或者首先会在搜狐矩阵内来进行嵌入?那么,如果选用第一种方式,则必须有着丰富的API接口,根据我的观察,这一点搜狗目前似乎还没有做到位;而如果选用第二种方式,则必须依托强势的市场力量,同时还需要依托丰富的API接口,基于前面的叙述,显然这一方式还不成熟。那么剩下的就是首先第三种方式了,事实上这也是搜狐产品一贯的方式,毕竟是门户嘛,随便拿一个频道出来,都有着大量的用户群,不差钱、不差资源的,要不怎么说门户都那么牛气冲天呢。
  如果选用第三种方案,又如何来实施呢?这首先要看搜狗云输入适用什么产品、什么人群。呃,不要拿板砖扔我,我知道这个问题其实很弱智,因答案显而易见:对于产品,显然是有输入需求的产品;对于人群,显然是有着大量输入需求的人群。OK,知道了这两点,就可以来盘点一下搜狐矩阵里哪些产品适合嵌入搜狗云输入法了:

  一、搜狐小纸条(http://me.sohu.com)。
  显然,这是最适合来做推广的一个途径,原因有二:
  1、搜狐小纸条是搜狐唯一的IM产品,在搜狗矩阵中有着大量的嵌入,可以说是横向联系搜狐用户的主要媒介之一(另外一个是Passport)。适合用来做推广。
  2、使用搜狐小纸条的用户必然有着输入需求,在这种情况下,嵌入云输入法是丰富小纸条用户体验的一种方法,同时也是推广云输入法的一种途径。

  搜狐小纸条嵌入云输入法想象图:
云输入法应用

  二、搜狐白社会(http://bai.sohu.com)。
  白社会是搜狐的SNS产品,这款产品里有着大量的用户间的互动,在这种情况下,嵌入云输入法不仅可以起到宣传产品品牌的作用,同时还增强可用度。
  想象效果图:
云输入法应用

  搜狐产品太多,就不一一列举了,可以预见,未来搜狐的产品,但凡涉及到输入的地方都有可能会嵌入云输入法。比如:邮箱、评论、社区、博客等等。只是在宣传上可能会采用不同的噱头,比如博客,就可能会这样宣传:搜狐博客,互联网自带中文输入法的第一大博客。

  最后严正声明:以上纯粹是个人观点,不代表搜狐官方意见,亦不代表。

2十一/099

NodeJS探索

一、什么是NodeJS?
第一眼看到这个词,估计你和我一样,以为它不过是一个JavaScript框架吧?如果是,那么首先恭喜你,说明你的思维是正常的。其次鄙视你:凭什么带JS的就一定是JavaScript框架?你丫做技术的吧?最看不起你们这帮做技术的了,跟姓韩的那谁似的,没一点文化。
生活经验告诉我们,牛人往往都不怎么正常,正常人往往都成不了牛人。比如说NodeJS的发明者,这家伙就曾叫嚣说:其实JavaScript更适合做服务器端的并发编程。估计很多人听到这话都笑了,嗯,原谅我的可耻,我也笑了。令人欣慰的是上帝没有笑。当年上帝说要光,于是就有人脱了个精光。今天,上帝说我相信这个人能成,于是这个人还真成了,他弄了这么个东西:NodeJS--基于V8引擎的,使用事件驱动模型而不是复杂的多线程来获得可伸缩性,类似Ruby的EventMachine和Python的Twisted的轻量级WEBServer。
是不是很有意思?这意味着什么我想大伙都清楚吧?嗯,如果这东东真的可用,那就是说,以后前段后端都可以都用JavaScript来编程了,这对于JS程序员来说,真是一个莫大的福音,因为你们再也不用看着那帮做后台的孙子的脸色干活了,可以翻身做后端了。
好,废话到此,那接下来就请跟着我,开始NodeJS的探索之旅。

二、安装!
安装前先从NodeJS的官方网站下载其源代码:

  1. [root@www source]# wget http://s3.amazonaws.com/four.livejournal/20091028/node-v0.1.15.tar.gz
  2. [root@www source]# tar xzvf node-v0.1.15.tar.gz
  3. [root@www source]# cd node-v0.1.15

安装NodeJS很简单,一般情况下,Linux下常用的三步走即可。但需要注意的是:NodeJS需要2.3以上版本Python的支持,否则安装无法继续。

打开tools/waf-light,看到如下代码:

  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. # Thomas Nagy, 2005-2009
  4.  
  5. # ...
  6.  
  7. import os, sys
  8. if sys.hexversion<0x203000f: raise ImportError("Waf requires Python >= 2.3")

从以上代码我们知道,在安装脚本中,在Python脚本的头部指定了#!/usr/bin/env python,这就使得如果你的系统安装了自带的Python程序,则有可能由于版本不够高而无法安装。比如我的系统,是把Python2.5安装在了/usr/local/python252,同时未删除系统自带的低版本Python,此时如果configure,则会出错。

好吧,那我们建一个软连接:

  1. [root@www source]# sh
  2. [root@www source]# cd /usr/local/sbin/
  3. [root@www source]# ln -s /usr/local/python252/bin/python2.5 python
  4. [root@www source]# python
  5. [root@www source]# exit

此时执行的/usr/bin/env python,即可使用我们自己编译的Python。
PS.直接建软连接就可以了,这里之所以到sh环境下,是为了看一下sh环境。

执行configure,安装nodejs:

  1. [root@www source]# ./configure --prefix=/var/iapps/nodejs
  2. [root@www source]# make && make install

三、初次试用:
一切顺利,安装完成,写个脚本试试:

  1. #!/var/iapps/nodejs/bin/node
  2.  
  3. var sys = require("/sys.js"), http = require("/http.js");
  4. http.createServer(function (req, res) {
  5.     setTimeout(function () {
  6.             res.sendHeader(200, {"Content-Type": "text/plain"});
  7.             res.sendBody("Hello,This is Laohan(www.handaoliang.com)!");
  8.             res.finish();
  9.         }, 2000);
  10.     }).listen(8000);
  11. sys.puts("Server running at http://127.0.0.1:8000/");

我相信,对于JavaScript程序员来说,这语法真是太熟悉了,除了第一、第二行之外。无论如何,我们要开始我们的梦想之旅了,那么接下来我们将example.js设置成可执行并运行它:

  1. [root@www source]# chmod +x example.js
  2. [root@www source]# ./example.js

此时屏幕显示:Server running at http://127.0.0.1:8000/
访问:http://127.0.0.1:8000/,如果看到页面输出:Hello,This is Laohan(www.handaoliang.com)!,那么恭喜你,安装成功了,接下来就需要发挥你自己的聪明才智,去实现各种强大的功能了。很激动人心吧?

后面将为大家深入分析NodeJS,敬请期待。

原创文章,转载请注明出处!

   下一页