• Posts tagged "chat"

Blog Archives

吐槽R的未来 – 统计圈群聊

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-future-group-chat/

r-group-chat

前言

本文来自于“统计圈”十几位中国R语言资深用户闲聊吐槽。话题的起因在于我最近发表的一篇文章:R是最值得学习的编程语言

由于R的未来我非常好看,但统计背景的同学们,从不同的角度又会有一些不一样的认识,因此,就有了这篇关于R未来的神吐槽。

目录

  1. 对话内容
  2. 出场人物
  3. 讨论的主题

1. 对话内容

邓一硕:这是临时会话。请各位哥哥们,兄弟们来讨论下R的优缺点。
邓一硕:今天张丹说了很多有意思的观点。
邓一硕:没准是未来的趋势之一

张晔:抛砖引玉吧。如果以现在学术圈的身份来看,R几乎是没有缺点的。因为对于我来说,最重要的是一门的快速将我的想法实现出来加以验证的语言。
张晔:我倾向于分工合作,做模型的用R做出原型,然后CS的学霸们再搞优化,抠性能。
张晔:当然,这对R的发展有点不利,R目前还不太像一门通用语言

张丹:我的观点写了篇文章,http://blog.fens.me/r-ideal/

刘思喆:张丹的观点比较客观,R更多关注的是快速实现,而不会太关心复杂度。也许有一天R的底层会重构,但这种分析数据的理念终会一统天下

邓一硕:@张丹 他还提了面向对象编程
邓一硕:@张丹 你可以把今天上午跟我说的说一说
邓一硕:比如,这个

oo

邓一硕:R最核心的就是数据分析理念

张丹:思喆体会的更深
张丹:等我再写一篇吧,R的面向对象编程。
张丹:现在只看到了Hadley的代码

邓一硕:嗯,这个有必要研讨下

李舰:我和张丹的经历正好相反,用过十一年的R和三年的JAVA。我觉得R主要强在统计分析的扩展性

张丹:用到了其他语言的一些设计模式

邓一硕:Hadley 就是计算机出身,所以,程序员的认同感可能更多吧

张丹:如何用R构建复杂的应用,如何让R更健壮

李舰:R搞的面向对象最大的好处只是掩饰自己的代码,对工程开发有害无益

张丹:就设计到更复杂一些的程序设计了
张丹:是的,r现在的函数编程思路,就想5年前的js
张丹:现在js已经完全面向对象化了

李舰:我写的代码不想让别人简单拿去时才用R5,平时两三个人写作用一下S4,要多态S3就够了

张丹:R面向对象,让开发者和使用者分离
张丹:这是一种非常好的设计

李舰:应用系统的用户没必要关心代码,封装和分离很重要。分析型系统模型和方法经常要变化和review,可读最重要。如果哪一天客户买基于R的系统时不担心里面封装的代码那就好办了
李舰:现在的客户不懂的不会买,懂的要关注实现过程,确保不会算错,黑盒白盒都要搞,烦啊。

张丹:呵呵

邓一硕:这个说的很好

邓一硕:继续讨论~

张丹:是因为用户还不信任你
张丹:另外,外包项目和产品不一样

李舰:信任应该是没问题的,主要是分析型的系统结果太重要,像我们现在的系统错个数可能影响非常大的金额,必须确保中间模型没有任何问题,这和那种只出几个图和报表的BI不一样

张丹:嗯,等第二用户,就不会这麻烦了

陈堰平:R的开发者实在太少了,尤其中国

李舰:国内的客户倒没这么专业,用法也不是雪中送炭而是锦上添花,所以结果没压力,但新问题又来了,以前我做过一个文本挖掘的系统,POC时真的用R做了不错的模型,可是交付时由于关系都搞定,R的部分比POC还简单
李舰:这说明假设当时我们没有那个能力,忽悠下来后也能交付,这就是国内的情况,坏处是门槛低竞争多卖不出价

陈堰平:嗯,这也是我这大半年来的感受

李舰:而且R的产品很难标准化一劳永逸,如果不忽悠的话,没个客户的数据不同模型可能千差万别,这和BI数据挖掘那些东西完全不同

张丹:可以尝试做个BI,慢慢标准化
张丹:或者rstudio的工具
张丹:培养用户习惯

李舰:唯一能做的是JAVA的壳标准化,R的模型热插拔,这样一来,严格的函数式编程反而是最方便的

张丹:呵呵,这个思路,直接了当。和我的产品一样

李舰:rstudio现在的状态是个玩具,开发人员没人会去用,用户又更喜欢界面和按钮

魏太云:用户蛮多,口碑很好啊

张丹:rstuido是一个入口
张丹:kniter,就是受益的,培养了用户一个新的习惯

魏太云:是啊,可以弄点好东西上去的。

李舰:rstudio的用户是R的用户,不是花钱的用户

魏太云:我觉得比Revolution有前途。
魏太云:没关系,先培养着。

张丹:比如rstudio,搞个企业分析工具
张丹:增加各种功能

李舰:不过rstudio是个非常好的平台,实现真正的云计算后直接网上卖模型那么前途无量

邓一硕:这个益辉有发言权

邓一硕:没错,云计算才是看点

魏太云:我觉得Tableau的很多功能Rstudio都可以做

张丹:入口培养了习惯,推广就容易了
张丹:是的
张丹:单纯做R的项目,没有前期培养,就像你说的,麻烦死了

魏太云:是啊,知名度很高,口碑很好。用户基础牢固。

邓一硕:

陈堰平:其实上,中国有模型需求的公司不多,倒不如数据展现来的直接

李舰:培养了也会继续麻烦的,我们的客户都是懂R的团队,都是培养了上十年的,但是模型的需求这东西每次都变,没办法

张丹:标准化

魏太云:我目前接触的需求都是从数据到展示,分析最简单的描述统计就够了。

李舰:这是R的竞争优势,没有别的可以取代。往BI那边走可以一劳永逸,但是没有优势,价格太低

张丹:把做过的模型,半价给第二个用户用
张丹:再1/4给第三个
张丹:找多用户,多写模型

李舰:我说的那些模型不是维度模型或者简单回归聚类什么的,比如一款药的药动学模型,都是绝密的东西。而且如果不是研发相同的药,也没法重用

魏太云:R方面复制性强的业务,我能想到的就是做更灵活的Tableau。

张丹:绝密的东西,开发已经赚够钱

邓一硕:这跟开发投资策略一样,基本都是绝密

张丹:已经高收益了

张丹:创新就是要承受麻烦

李舰:对,这就是我说的R的价值,每次项目是新的模型,利润很高。不然就是往报表BI这条路走,就是太云说的Tableau这样
李舰:后面一条路就是我在前一家公司一直做的东西,JAVA搭系统,FLEX做前端,R做分析引擎。搞了两年多,产品也搞了几个,项目也不算少
李舰:不过利润也一般,只是时间自由好吃好喝大家开心而已
李舰:三年前觉得比较没有成就感,就到芒果来了

魏太云:我现在就需要这样的东西。哈哈。

邓一硕:我现在也没有成就感

魏太云:当然,成就还没有,亚历山大。

邓一硕:嗯,不要跑题,继续吐槽

李舰:基于R的标准化报表和简单分析的工具很难卖出好价,要靠量取胜,对销售能力要求很高,还要会桌下交易之道,这是我这些年感觉唯一没看清而且没有信心的地方,所以我对vivian和堰平还是很有信心的

邓一硕:

魏太云:同不懂交易。

邓一硕:我觉得实现自己的价值,被认同很重要

李舰:现在芒果这种模式算是能实现R真正的价值,也算是真的用好了数据没有忽悠,也没什么竞争对手,但是受众比较窄

邓一硕:不懂交易就走技术

陈堰平:同不喜欢做销售,但我更有做构架师的天赋,好吧,是我YY的
陈堰平:老罗说,人们年轻的时候总爱把创作冲动误以为创作天赋

邓一硕:这话说得好

寇强:作为一个码农,视角是不同的

邓一硕:说说你的视角

寇强:码农都要研究个开源项目以修炼内功的,但未必真的就靠这个项目吃饭

陈堰平:

寇强:某些意义上讲,R引擎是必须推倒重写的

邓一硕:霸气

寇强:Oracle就在干这个呀

陈堰平:毕竟生的早啊

寇强:做这个的主要技术人员就在普度大学

邓一硕:怡轩那里
邓一硕:不知道怡轩认识不认识

魏太云:赵扬导师?

邱怡轩:CS的

寇强:Purdue的那个实验室写了很多R底层分析的东西

魏太云:开源吗?

邓一硕:轩哥现身

寇强:越往底层去,愈发觉得R的设计缺乏远见,已经和时代脱节了

陈堰平:七十年代出的,设计师怎么知道后来的事

寇强:R里的black corner很多,而且很多没有文档注明,比如snow的并行上限是128,这个是写在源文件里的,不在编译前修改,就别指望更大规模的并行
寇强:对未来估计不足,就面临重写甚至不兼容,参考python2和python 3

邓一硕:

魏太云:你来演讲R中的那些坑吧

邓一硕:轩哥没有发表见解阿

陈堰平:以后出个R++吧

寇强:印象里有个用C++重写R的项目就这个名字。。。

陈堰平:有个用java的叫renjin

寇强:Renjin背后是家startup,BeDataDriven
寇强:最新的是个RC版
寇强:12年他们在useR上给过一个talk
寇强:R语法有种怪怪的感觉,函数式和面向对象同时支持的脚本语言真的不多

邓一硕:嗯~

张丹:js

寇强:我觉得js比R顺眼多了。。。

张丹:R就像5年前的js

寇强:那个时代没赶上。。。

陈堰平:js的callback函数的用法,一开始我还真不习惯

邓一硕:这种比较很有意思
邓一硕:julia呢
邓一硕:大家对julia怎么看

寇强:开发者出身都不错,也足够激情

邓一硕:我比较看好julia,野心勃勃,实力也足够

汪磊:这…不是有个群么…

邓一硕:那是八卦群,这个是临时群,讨论完就解散

汪磊:额,我是说julia群

寇强:我的个人取向,老实写C++或者Java,饭碗最重要

陈堰平:我也转到java了
陈堰平:跪求一份java程序猿的工作
陈堰平:写java程序都不像写R一样那么费脑子

汪磊:算了…除了楠神不在,其他都拉进来了…
汪磊:把那个群解散得了
汪磊:我喜欢java的思路,c++是杂货铺…

肖楠:感觉R现在在学术界还挺受重视的,大家抓紧时间写包发文章灌水吧

汪磊:一硕,我把楠神拉进来是正确的,哈哈哈

肖楠:嗯,所以没什么可吐槽未来的,这个群可以解散了 [Grin]

寇强:说得对,Java就适合我这种智商余额不足的

寇强:Java是血统好的高富帅,一直对我等低端码农很照顾

汪磊:码神一定特喜欢scala

陈堰平:嗯,不是人读的代码

寇强:其实吧,我认识的学霸都很推崇函数式

汪磊:lambda就和做题一样爽

寇强:学霸,您好!

汪磊:我是渣…看答案都看不懂

谢益辉:有RStudio在,R就不会亡!语言的兴衰不会因为它本身是否渣。JavaScript渣吗?大家还是前赴后继往上扑。R有没有前途取决于有没有人发掘它的魔法,并巧妙地和其它语言和框架结合起来,RStudio做了很多这样的事情,只有想不到,没有做不到。

陈堰平:是啊

谢益辉:R最大的危险在于核心头目没了当年搞统计的激情

陈堰平:js这样几周时间写出来的语言,出生就很草率了,还不一样活到现在

谢益辉:现在钻进了牛角尖,净搞些和R包作者过不去的事情,参见src/library/tools/R/check.R

汪磊:js是事实标准…
汪磊:统计的事实标准R,现在有被Python干下来的趋势啊

谢益辉:是有这个趋势,这个过程要花多久很难说

陈堰平:那没关系,反正也影响不了统计学家的饭碗

谢益辉:统计学习巨头trevor hastie上课一天到晚推荐R/RStudio,上周还开始讲R markdown了
谢益辉:不知道这个网络课程有多少人在上

陈堰平:课程在哪儿?
谢益辉:statlearning.class.stanford.edu

陈堰平:ok

寇强:实话实说,码农更喜欢python

李舰:程序员没有喜欢R的,我当了几年纯IT男之后有段时间完全放弃了R,不过后来发现R的价值不在语言,当时间急剧不够很多事情没办法深究但又需要能有结果的时候R是最好的选择

陈堰平:对啊,从这个意义上讲,R是软件

魏太云:Python的统计积累也蛮快。
魏太云:调用R也很方便。

李舰:当年学JAVA的都抬不起头来,就连C#这样的东西都一度很火,可是今天仍然没见到JAVA被搞下来

魏太云:有这历史?哈哈。

汪磊:没有吧C#03年火的时候,JAVA一直坚挺着

李舰:python和julia都是好东西,就像C++当年对JAVA那样,可是北大青鸟出来的人就可以直接上JAVA的大项目,企业就是要用,这就是标准

汪磊:要是培训的话,明显R难一些吧,语法都看不懂…

寇强:Java!我的饭碗!

李舰:JAVA坚挺是个结果,那些年软件学院里非常歧视JAVA

汪磊:箭头往左指,我到现在没看懂是什么意思
汪磊:到现在为止,R的使用时间没超过五分钟…

魏太云:为啥我觉得R语法蛮简单

李舰:从我培训和上课的经历来看,反而是非CS背景的人学R更快

陈堰平:R难的倒不是语法,而是统计的知识
陈堰平:IT的人错把统计方法的部分当做了语法的一部分了

张晔:同楼上

陈堰平:所以其实像我这样从R转到java的还是有很大优势的
陈堰平:貌似舰哥就是这个路线,舰哥是我的偶像啊

李舰:CS的人容易纠结R的细节和困惑,而且有点完美主义,时间足够长的话可以成为高手,但实际上很少有人跨过这一步,像这个群里的各位都不是普通人,不一定能体会他们的感觉

汪磊:统计方法不就是算法么…

李舰:没CS背景的很听话,只管操作函数,很短时间就能用R做不少事情。我去年在浙大软院上了一学期的课,感觉很明显

陈堰平:不啊,基本上其他编程语言的语法,都是那几大类,再加上常用类库。东西都是很固定的,所以他们基本上会了一门语言,另一门语言就跟学门方言差不多了

陈堰平:什么io,数据库操作,网络编程,就那么多东西。还有现成框架可以用,做的项目也就那么几类,也有现成代码可以借鉴

李舰:问题是R没那么规范,用学其他语言的习惯去学处处是困惑

陈堰平:所以北大青鸟蓝翔技校出来的就能做项目了

李舰:堰平干嘛要转JAVA,我毕业一年后就再也不写JAVA了

魏太云:我觉得看吴喜之前的数据到结论 复杂数据 入门就很好。

陈堰平:不是规范的问题了,根本就能当编程语言学。当编程语言学,看R语言编程艺术这本书,CS的人会觉得R做不了什么

李舰:是啊,我去年就用吴老师那本书当教材的

陈堰平:我觉得java挺好啊,不用学那么细,入个门,以后写代码的事交给别人做,我只管指导

魏太云:R是奇葩啊。

汪磊:程序重要的是数据结构和算法。一个语言如果能方便的完成这件事才好用。R几乎就不怎么支持高级数据结构啊。比如做图论需要二叉树,R表示起来就不高效啊

汪磊:matlab也有这个问题

陈堰平:二叉树。。。可以用类啊。。。好吧,R语言编程艺术里有个例子,表示二叉树是用矩阵,回到了fortran那个年代。本来就不是设计来做这个的

汪磊:本来O(nlogn)的问题,用矩阵表示,就不知道复杂度提升到多少了…
汪磊:还有建最小堆什么的…这些都是非常常用的数据结构…

张晔:上Rcpp啊

汪磊:所以么…这语言让人学着很沮丧…

张晔:现在又有ReferenceClass

陈堰平:那就不是R了

张晔:。。。不要那么完美主义

邱怡轩:确实是一件很好玩的事,设计R的时候只关心统计关心的数据,统计不关心float和double,它就不加区分,统计关心factor和数据框,它就设计因子和数据框。等统计学家关心图论的时候,才发现R不够用了,而之前一直没人关心。

邱怡轩:或许本来就不应该对R在通用编程上有过高的期望,安分守己就好。

汪磊:高级计算器…和matlab一样…

李舰:对,很多写程序搞科学的人容易完美主义,喜欢追求一个通用的好东西
李舰:这要放在摄影论坛,完全是另一种结果。就是一镜走天下怎么选镜头的问题

魏太云:是啊,我们不能要求一个语言干所有的事情。

李舰:如果有个像R这样用要你命三千的方式把长焦人像广角微距什么的绑在一起,估计做梦都笑醒

汪磊:还是有区别的。设计良好的语言是能完成这件事的。难度在于既有算法的迁徙难度

李舰:反而那些18-300的副厂头不受待见
李舰:那个设计良好的通用语言还没出来,不知什么时候可以出来,就像色友一直期待的能用的18-300头还没出来一样

魏太云:目前都指望julia的感觉。

汪磊:比如Python, julia,它们明显可以做到R的事情,性能已经比R好了
汪磊:缺点是还是不像预计的那样和C能媲美
汪磊:迁徙已经用R实现的算法倒是个问题
汪磊:我用MATLAB计算元素为0或1矩阵,要求矩阵不存在长度低于某个值的封闭围线,仿真跑了一个多小时,julia是一分钟不到。python当时没使用。R不会用…
汪磊:C实现的编程难度太大…

魏太云:为啥?

汪磊:脚本语言好实现…

魏太云:没看懂题目。。

汪磊:哦,我是做编码译码的…
汪磊:需要搜索满足条件的好码…

魏太云:能重新解释下吗?

汪磊:[1 1 0; 0 1 1; 1 0 1]

魏太云:貌似明白了。

汪磊:这个矩阵就是有一个封闭围线,长度是6条线段
汪磊:我做的矩阵维度是几千乘几万大小的…

魏太云:这个Julia很合适。

汪磊:python应该也行
汪磊:其实就是图论,属于二分图

寇强:大而全的语言最后都死得很惨
寇强:参考IBM当年折腾出来的PL1
寇强:Programming language one,妄图一门语言搞定所有需求

张晔:julia可称小而全。虽然我还是不看好它

寇强:既然学霸这么说,我觉得我可以退订他家的邮件列表了

张晔:寇学霸别磕碜我了。
张晔:话说您不打算申请一下julia的GSoC?

寇强:今年继续在R,明年去一个C++的机器学习项目,毕业前的终极目标是apache
寇强:LLVM和GCC都急需您这样的高手拯救

张晔:。。。别黑,现在的梦想是水文章,水完抱群里的大腿们。

邓一硕:高质量吐槽
邓一硕:大家接着吐槽 吐完总结下 散群

寇强:说实话呀,我现在对R的看法,只是当作学习工具而已
寇强:未来谋生未必靠这玩意

邓一硕:我用R就是实现自己的目的,时间快是最大的要求

寇强:个人把程序员分三种,这个分类与NB程度无直接关系

邓一硕:说说看

寇强:第一类是做语言开发的,比如里奇呀,gosling呀
寇强:第二类是做框架和工具的,比如EJB和SSH
寇强:第三类是做直接面向用户的应用的
寇强:R应该算是个工具和框架,对它要求不能太多
寇强:个人的人生理想事写个有人用的工具出来,但愿能实现

邓一硕:认同

刘思喆:恩,在企业it部门里,R也只能搞定一部分需求,还需要配合很多其他工具。当然如果只是做数据分析的话,完全能搞定
刘思喆:我非常赞同镜头的类比,R就是玩微距的

邓一硕:嗯,大家继续讨论

刘思喆:还有常被吐槽的就是R的慢,但很少有人意识到它最初的设计压根就不是搞这个的

寇强:当年带我编程入门的大哥教导我,程序员的确不应该重复造轮子,但重复造轮子的能力是必须有的

寇强:我这自不量力地看R的源代码也是因为这个教导

刘思喆:要搞明白还真要看源代码,里面神奇的东西很多

寇强:R的源码读起来总有一种先秦古籍的感觉。。。

陈堰平:都是些什么?文言文lisp吗

殷腾飞:从语言角度,R纵有万千缺点,有一个优点也够它撑十年了,那就是应用的数量,用户数量和目前的跨领域的影响力。比如bioc 700+的包,和完整的生物信息数据结构,给R产生了很大附加值,其他语言都比不了的。R速度和语言缺点都被吐槽吐烂了还是一样坚挺这么久,不过R要是不思进取,顽固不化,十几年以后感觉应该会被超越的。

殷腾飞:revolution对R在业界的推动,包括Rstudio的推动,也是R短期一定还会大量占有市场的原因。还有一个,关心性能和语言本身的统计学家,比关心应用和使用体验的统计学家少太多太多了。。。

殷腾飞:个人角度出发,不考虑社区发展的话,我是完全不关心语言战争和未来,现在谁能更好解决问题就用谁。。。

邓一硕:嗯~
邓一硕:把大家讨论的甩甩水就是一篇好文

魏太云:是啊

邓一硕:吐槽差不多了

陈堰平:谁总结一下写篇?

邓一硕:准备散去咯

肖楠:咳咳,Bioconductor现在独立搞了一个BiocCheck,比CRAN的check还严格,查了一遍以后觉得我的精神境界都得到了提升 。。。

魏太云:Rcpi?

谢益辉:我觉得这些事情都很无聊

邓一硕:不过,听听大家的看法还是开阔很多

邓一硕:大家吐槽结束,可以散群了

2. 出场人物

按说话的次序排列

硕一邓, 张晔, 张丹, 刘思喆, 李舰, 陈堰平, 魏太云, 寇强, 邱怡轩, 回归线, 肖楠, 谢益辉, 殷腾飞

硕一邓

张晔

张丹

刘思喆

李舰

陈堰平

魏太云

寇强

邱怡轩

汪磊

稍后补充…

肖楠

谢益辉

殷腾飞

3. 讨论的主题

接下来,我总结一下,上面吐槽的各种跨界主题。

  • 学术派和IT人看R的区别
  • 从IT人转到R做统计建模
  • 从统计人转到IT做程序员
  • R的面向对象编程
  • R的底层需要重写
  • R的理念会一统天下
  • R的高端建模
  • R的通用模型
  • 国内的统计项目太低端
  • 有RStudio在,R就不会亡
  • Java和R的配合的重要性
  • R++是一个C++重写R的项目
  • 现在的R就像5年前的JS
  • Julia前景很乐观?!
  • 其他语言的讨论Java,Python,Matlab,Julia,C++,Javascript

这就是圈里的吐槽…

转载请注明出处:
http://blog.fens.me/r-future-group-chat/

打赏作者

Socket.io在线聊天室

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-socketio-chat/

socketio

前言

网络聊天室在web1.0的时代就出现了,但当时技术支持比较有限,大都是通过浏览器插件BHO,JavaApplet,Flash实现的。如今HTML5技术风起云涌,通过websocket实现的网络聊天室,被定义为websocket的第一个实验,就像Hello World一样的简单。

今天我也动手完成了这个实验,感觉真的很爽!

目录

  1. socket.io介绍
  2. 服务器端和客户端通信设计
  3. 服务器端实现
  4. 客户端实现
  5. 完整案例代码

1. socket.io介绍

socket.io一个是基于Nodejs架构体系的,支持websocket的协议用于时时通信的一个软件包。socket.io 给跨浏览器构建实时应用提供了完整的封装,socket.io完全由javascript实现。

基于Nodejs实现webscoket其他的框架,请参考文章:Nodejs实现websocket的4种方式

2. 服务器端和客户端通信设计

chat

上图中client1 和 server 描述通信过程,client2描述对其他的客户端,通过广播进行消息通信。

  1. client1向server发起连接请求
  2. server接受client的连接
  3. client1输入登陆用户名
  4. server返回欢迎语
  5. server通过广播告诉其他在线的用户,client1已登陆
  6. client1发送聊天信息
  7. server返回聊天信息(可省略)
  8. server通过广播告诉其他在线的用户,client1的聊天消息
  9. client1关闭连接,退出登陆
  10. server通过广播告诉其他在线的用户,client1已退出

我们看一下测试截图:
chat2

  1. 左边: aaa 登陆
  2. 右边: bbb 登陆
  3. 左边: aaa 收到 bbb登陆欢迎消息
  4. aaa 和 bbb 实现对话
  5. 右边: bbb 刷新浏览自动退出
  6. 左边: aaa 收到 bbb的退出消息
  7. 右边: CCC 登陆
  8. 左边: aaa 收到 CCC 登陆欢迎消息
  9. aaa 和 CCC 实现对话

3. 服务器端实现

我们这里使用socket.io和express3的混合模式,让HTTP请求和WebSocket请求都使用3000端口。

服务器端实现,只有一个核心文件app.js。


//引入程序包
var express = require('express')
  , path = require('path')
  , app = express()
  , server = require('http').createServer(app)
  , io = require('socket.io').listen(server);

//设置日志级别
io.set('log level', 1); 

//WebSocket连接监听
io.on('connection', function (socket) {
  socket.emit('open');//通知客户端已连接

  // 打印握手信息
  // console.log(socket.handshake);

  // 构造客户端对象
  var client = {
    socket:socket,
    name:false,
    color:getColor()
  }

  // 对message事件的监听
  socket.on('message', function(msg){
    var obj = {time:getTime(),color:client.color};

    // 判断是不是第一次连接,以第一条消息作为用户名
    if(!client.name){
        client.name = msg;
        obj['text']=client.name;
        obj['author']='System';
        obj['type']='welcome';
        console.log(client.name + ' login');

        //返回欢迎语
        socket.emit('system',obj);
        //广播新用户已登陆
        socket.broadcast.emit('system',obj);
     }else{

        //如果不是第一次的连接,正常的聊天消息
        obj['text']=msg;
        obj['author']=client.name;      
        obj['type']='message';
        console.log(client.name + ' say: ' + msg);

        // 返回消息(可以省略)
        socket.emit('message',obj);
        // 广播向其他用户发消息
        socket.broadcast.emit('message',obj);
      }
    });

    //监听出退事件
    socket.on('disconnect', function () {  
      var obj = {
        time:getTime(),
        color:client.color,
        author:'System',
        text:client.name,
        type:'disconnect'
      };

      // 广播用户已退出
      socket.broadcast.emit('system',obj);
      console.log(client.name + 'Disconnect');
    });

});

//express基本配置
app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

// 指定webscoket的客户端的html文件
app.get('/', function(req, res){
  res.sendfile('views/chat.html');
});

server.listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

var getTime=function(){
  var date = new Date();
  return date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
}

var getColor=function(){
  var colors = ['aliceblue','antiquewhite','aqua','aquamarine','pink','red','green',
                'orange','blue','blueviolet','brown','burlywood','cadetblue'];
  return colors[Math.round(Math.random() * 10000 % colors.length)];
}

4. 客户端实现

这里我们需要定义几个文件:chat.html, chat.js, jquery.min.js, main.css

1). views/chat.html


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Socket.io - Simple chat</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
<script src="javascripts/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="javascripts/chat.js"></script>
</head>
<body>
<h1>Socket.io - Simple chat room</h1>
<div>
<span id="status">Connecting...</span>
<input type="text" id="input"/>
</div>
<div id="content"></div>
</body>
</html>

2). public/javascript/chat.js


$(function () {
var content = $('#content');
var status = $('#status');
var input = $('#input');
var myName = false;

//建立websocket连接
socket = io.connect('http://localhost:3000');
//收到server的连接确认
socket.on('open',function(){
status.text('Choose a name:');
});

//监听system事件,判断welcome或者disconnect,打印系统消息信息
socket.on('system',function(json){
var p = '';
if (json.type === 'welcome'){
if(myName==json.text) status.text(myName + ': ').css('color', json.color);
p = '<p style="background:'+json.color+'">system @ '+ json.time+ ' : Welcome ' + json.text +'</p>';
}else if(json.type == 'disconnect'){
p = '<p style="background:'+json.color+'">system @ '+ json.time+ ' : Bye ' + json.text +'</p>';
}
content.prepend(p);
});

//监听message事件,打印消息信息
socket.on('message',function(json){
var p = '<p><span style="color:'+json.color+';">' + json.author+'</span> @ '+ json.time+ ' : '+json.text+'</p>';
content.prepend(p);
});

//通过“回车”提交聊天信息
input.keydown(function(e) {
if (e.keyCode === 13) {
var msg = $(this).val();
if (!msg) return;
socket.send(msg);
$(this).val('');
if (myName === false) {
myName = msg;
}
}
});
});

3). public/javascript/jquery.min.js
从jquery官方下载: http://jquery.com/

4). public/css/main.css


* {padding:0px; margin:0px;}
body{font-family:tahoma; font-size:12px;margin:10px;}
p {line-height:18px;padding:2px;}
div {width:500px;}
#content { 
    padding:5px; 
    background:#ddd; 
    border-radius:5px;
    border:1px solid #CCC; 
    margin-top:10px; 
}
#input { 
    border-radius:2px; 
    border:1px solid #ccc;
    margin-top:10px; 
    padding:5px; 
    width:380px;  
}
#status { 
    width:100px; 
    display:block; 
    float:left; 
    margin-top:15px; 
}

5. 完整案例代码

项目已经上传到github: https://github.com/bsspirit/chat-websocket

下载,安装,启动服务器


git clone https://github.com/bsspirit/chat-websocket.git
npm install
node app.js

打开浏览器
可以多打开几个窗口,模拟不同用户有的对话。
http://localhost:3000

做完实验,感觉棒极了。技术创新的革命!!

转载请注明出处:
http://blog.fens.me/nodejs-socketio-chat/

打赏作者