PHP WebSocket Chat Application 2.0 实现聊天功能

Even though it hasn’t worked for quite some time now, my previous PHP WebSocket chat application has garnered quite a bit of attention and is still one of my most heavily trafficked posts. As a result I thought I’d provide you all with a working script as of Feb 15, 2012. Because I’m your typical lazy developer, I’ll be building on top of other peoples’ work – most notablyPHPWebSocket.

You can download the final script here. According to the Wikipedia articleon WebSockets, it should work in IE10+, Firefox 7+ and Chrome 14+. Personally I tested with Chrome 17.0.963.46 and Firefox 10.0.1.

I want to stress that this tutorial is designed to be extremely basic and as such does not give alot of functionality out of the box (but provides all the tools necessary to add more). It’s simply a working example of a PHP-based WebSocket server.

 

The Implimentation – Server Side

PHP WebSocket ServerPHP WebSocket Server 

While the PHPWebSocket class works, it puts alot of variables and constants into the global scope. This is a big no-no in my opinion so I moved the entire script into a class PHPWebSocket and added the following functions:

  • bind: Binds a given function name to a given event. Valid events include:
    • open: Triggers as a user connects
    • close: Triggers as a user disconnects
    • message: Triggers when a user sends data to the server
  • unbind: Unbinds all functions from a given event, or all functions from all events if no event name is given.
  • log: Logs a message to the standard output Continue reading “PHP WebSocket Chat Application 2.0 实现聊天功能”

几点建议,让Redis在你的系统中发挥更大作用

Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储;它的数据模型非常独特,用的是单线程。另一个大区别在于,你可以在开发环境中使用Redis的功能,但却不需要转到Redis。

转向Redis当然也是可取的,许多开发者从一开始就把Redis作为首选数据库;但设想如果你的开发环境已经搭建好,应用已经在上面运行了,那么 更换数据库框架显然不那么容易。另外在一些需要大容量数据集的应用,Redis也并不适合,因为它的数据集不会超过系统可用的内存。所以如果你有大数据应 用,而且主要是读取访问模式,那么Redis并不是正确的选择。

然而我喜欢Redis的一点就是你可以把它融入到你的系统中来,这就能够解决很多问题,比如那些你现有的数据库处理起来感到缓慢的任务。这些你就可 以通过Redis来进行优化,或者为应用创建些新的功能。在本文中,我就想探讨一些怎样将Redis加入到现有的环境中,并利用它的原语命令等功能来解决 传统环境中碰到的一些常见问题。在这些例子中,Redis都不是作为首选数据库。

显示最新的项目列表

下面这个语句常用来显示最新项目,随着数据多了,查询毫无疑问会越来越慢。

  1. SELECT * FROM foo WHERE ... ORDER BY time DESC LIMIT 10

在Web应用中,“列出最新的回复”之类的查询非常普遍,这通常会带来可扩展性问题。这令人沮丧,因为项目本来就是按这个顺序被创建的,但要输出这个顺序却不得不进行排序操作。

类似的问题就可以用Redis来解决。比如说,我们的一个Web应用想要列出用户贴出的最新20条评论。在最新的评论边上我们有一个“显示全部”的链接,点击后就可以获得更多的评论。

我们假设数据库中的每条评论都有一个唯一的递增的ID字段。

我们可以使用分页来制作主页和评论页,使用Redis的模板:

-每次新评论发表时,我们会将它的ID添加到一个Redis列表: Continue reading “几点建议,让Redis在你的系统中发挥更大作用”

连载之四:深度揭秘微信的敏捷开发与流程管理

IT海盗:这是微信的解构与建构连载的第四篇,依然干货连连,读起来激情澎湃。微信敏捷开发中的“微循环”是什么?张小龙怎样在看似“混乱”的流程管理中无招胜有招?让我们一起来享受微信连载第四篇!

点击这里查看前三篇并注意首篇开头的声明:(一)微信的诞生(二)微信的开发历程; (三)微信团队:这里像艺术中心、研究院、学校

敏捷是一种态度,试错是一种信仰。——微信团队Harvey

敏捷开发

敏捷开发是一种常用的软件开发模式,与传统的“瀑布式开发”相比,敏捷开发能够持续满足不断变化的需求变动。微信团队的情况正是这样,“整个开发过程中产品会不断修改,这是我们的特色。”Harvey说,“哪怕在发布前的十分钟,我们也要允许产品决策者提出变更。”“为了给产品决策者提供最大的自由度,敏捷原则成为整个开发流程的指导原则,”“极度敏捷”也成为技术团队乃至整个微信团队的追求。 Continue reading “连载之四:深度揭秘微信的敏捷开发与流程管理”

php在linux系统下mkdir()函数的权限问题

php在linux系统下mkdir()函数的权限问题 php代码创建一个目录,期望的目录权限是0777,但结果权限却是0755。 mkdir(“file”,0777); 结论: 1、php中的mkdir()函数创建的指定目录权限只能小于等于系统umask设定的默认权限。 2、php中的chmod()函数不受系统umask设定的权限影响,可以设置比系统默认权限大的权限。 3、linux系统中的mkdir命令可以设置大于默认值的权限。 总结: 从上述结论中可以得出如下结果。在用php中的mkdir()函数创建读写权限目录的时候,不要直接使用mkdir函数指定权限,以避免系统umask的影响。可以用如下代码: mkdir(“file); chmod(“file”,0777);

nginx url重写问题

发现一个问题,如果这样设置,

if (!-e $request_filename)
{
#地址作为将参数rewrite到index.php上。
rewrite ^/(.*)$ /index.php/$1;
#若是子目录则使用下面这句,将subdir改成目录名称即可。
#rewrite ^/subdir/(.*)$ /subdir/index.php/$1;
}
地址可以重定向
比如:
重启Nginx以后,http://localhost/project/Index/insert, http://localhost/project/index.php/Index/delete 这样的URL

但问题是index.php后面加一个/就会502 Bad Gateway报错,好像与隐藏index.php没有什么关系,框架是thinkphp,这是什么问题
nginx/1.5.2
php 5.5.1

后来将nginx版本降至1.0.15后,添加一段location就可以了? 虽然两个版本的配置文件有不一样,分析后得出还是location中的问题

 

location / {

#ThinkPHP Rewrite

if ( !-e $request_filename ){

rewrite ^/(.*)$ /index.php/$1;

}

}

 

location ~ .php($|/){

#配置PHP支持PATH_INFO进行URL重写

set $script     $uri;

set $path_info  “”;

if ($uri ~ “^(.+?.php)(/.+)$”) {
set $script     $1;

set $path_info  $2;

}

fastcgi_pass   127.0.0.1:9000;

fastcgi_index  index.php;

include fcgi.conf;

fastcgi_param  SCRIPT_FILENAME    $document_root$script;

fastcgi_param  SCRIPT_NAME        $script;

fastcgi_param  PATH_INFO          $path_info;

}

 

第一段只是隐藏index.php,第二段才是解析后面的方法与参数设置,这样写才能有效运行.

javascript 随机数生成方法

1.使用内置的随机数发生方法:
Math.random(); //该方法产生一个0到1之间的浮点数。
Math.floor(Math.random()*10+1); //1-10
Math.floor(Math.random()*24);//0-23

2.基于时间,亦可以产生随机数:
var now=new Date();
var number = now.getSeconds(); //这将产生一个基于目前时间的0到59的整数。

var now=new Date();
var number = now.getSeconds()%43; //这将产生一个基于目前时间的0到42的整数。

3.
一个相当优秀的的随机数发生器程序,能应用于许多领域。

<script language=”JavaScript”><!–
// The Central Randomizer 1.3 (C) 1997 by Paul Houle (houle@msc.cornell.edu)
// See: http://www.msc.cornell.edu/~houle/javascript/randomizer.html
rnd.today=new Date();
rnd.seed=rnd.today.getTime();
function rnd() {
rnd.seed = (rnd.seed*9301+49297) % 233280;
return rnd.seed/(233280.0);
};
function rand(number) {
return Math.ceil(rnd()*number);
};
// end central randomizer. –>
</script>

 

基于一致性hash算法 C++实现详解

在《基于一致性hash算法(consistent hashing)的使用详解》一文中已经介绍了一致性hash的基本原理,本文将会对其具体实现细节进行描述,并用c++语言对一致性hash进行了简单的实现

 

一致性hash算法实现有两个关键问题需要解决,一个是用于结点存储和查找的数据结构的选择,另一个是结点hash算法的选择。

首先来谈一下一致性hash算法中用于存储结点的数据结构。通过了解一致性hash的原理,我们知道结点可以想象为是存储在一个环形的数据结构上(如下图),结点A、B、C、D按hash值在环形分布上是有序的,也就是说结点可以按hash值存储在一个有序的队列里。如下图所示,当一个hash值为-2^20的请求点P查找路由结点时,一致性hash算法会按hash值的顺时针方向路由到第一个结点上(B),也就是相当于要在存储结点的有序结构中,按查询的key值找到大于key值中的最小的那个结点。因此,我们应该选择一种数据结构,它应该高效地支持结点频繁地增删,也必须具有理想的查询效率。那么,红黑树可以满足这些要求。红黑树是一颗近似平衡的一颗二叉查找树,因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。 因此,我们选择使用红黑树作为结点的存储结构,除了需要实现红黑树基本的插入、删除、查找的基本功能,我们还应该增加另一个查询lookup函数,用于查找大于key中最小的结点。 Continue reading “基于一致性hash算法 C++实现详解”

memcached的分布式

memcached的分布式

正如第1次中介绍的那样, memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能。 服务器端仅包括 第2次、 第3次 前坂介绍的内存存储功能,其实现非常简单。 至于memcached的分布式,则是完全由客户端程序库实现的。 这种分布式是memcached的最大特点。

memcached的分布式是什么意思?

这里多次使用了“分布式”这个词,但并未做详细解释。 现在开始简单地介绍一下其原理,各个客户端的实现基本相同。

下面假设memcached服务器有node1~node3三台, 应用程序要保存键名为“tokyo”“kanagawa”“chiba”“saitama”“gunma” 的数据。

memcached-0004-01.png Continue reading “memcached的分布式”

CRC32算法详细推导

CRC 算法的数学基础

CRC 算法的数学基础就不再多啰嗦了,到处都是,简单提一下。它是以 GF(2) 多项式算术为数学基础的,GF(2) 多项式中只有一个变量 x ,其系数也只有 0 和 1 ,比如:

1 *x^6 + 0*x^5 + 1*x^4 + 0*x^3 + 0*x^2 +1*x^1 + 1*x^0

= x^6 + x^4 + x + 1

加减运算不考虑进位和退位。说白了就是下面的运算规则:

0 + 0 = 0    0 – 0 = 0

0 + 1 = 1    0 – 1 = 1

1 + 0 = 1    1 – 0 = 1

1 + 1 = 0    1 – 1 = 0
看看这个规则,其实就是一个异或运算。

每个生成多项式的系数只能是 0 或 1 ,因此我们可以把它转化为二进制形式表示, 比如 g(x)=x^4 + x + 1 ,那么 g(x) 对应的二进制形式就是 10011 , 于是我们就把 GF(2) 多项式的除法转换成了二进制形式,和普通除法没有区别,只是加减运算没有进位和退位。

比如基于上述规则计算 11010/1001 ,那么商是 11 ,余数就是 101 ,简单吧。

 

CRC 校验的基本过程

采用 CRC 校验时,发送方和接收方用同一个生成多项式 g(x) , g(x) 是一个 GF(2) 多项式,并且 g(x) 的首位和最后一位的系数必须为 1 。

CRC 的处理方法是:发送方用发送数据的二进制多项式 t(x) 除以 g(x) ,得到余数 y(x) 作为 CRC 校验码。校验时,以计算的校正结果是否为 0 为据,判断数据帧是否出错。设生成多项式是 r 阶的(最高位是 x^r )具体步骤如下面的描述。

发送方:

1 )在发送的 m 位数据的二进制多项式 t(x) 后添加 r 个 0 ,扩张到 m+ r 位,以容纳 r 位的校验码,追加 0 后的二进制多项式为  T(x) ;

2 )用 T(x) 除以生成多项式 g(x) ,得到 r 位的余数 y(x) ,它就是 CRC 校验码;

3 )把 y(x) 追加到 t(x) 后面,此时的数据 s(x) 就是包含了 CRC 校验码的待发送字符串;由于 s(x) = t(x) y(x) ,因此 s(x) 肯定能被 g(x) 除尽。

接收方:

1 )接收数据 n(x) ,这个 n(x) 就是包含了 CRC 校验码的 m+r 位数据;

2 )计算 n(x) 除以 g(x) ,如果余数为 0 则表示传输过程没有错误,否则表示有错误。从 n(x) 去掉尾部的 r 位数据,得到的就是原始数据。

生成多项式可不是随意选择的,数学上的东西就免了,以下是一些标准的 CRC 算法的生成多项式:

标准 生成多项式 16 进制表示
CRC12 x^12 + x^11 + x^3 + x^2 + x + 1 0x80F
CRC16 x^16 + x^15 + x^2 + 1 0x8005
CRC16-CCITT x^16 + x^12 + x^5 + 1 0x1021
CRC32 x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11+ x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 0x04C11DB7

Continue reading “CRC32算法详细推导”

oracle与db2的区别比较(转)

系统结构概述

首先,我们需要理解 Oracle 使用的架构,并理解它与 DB2 的不同之处。图 1 展示了 Oracle 的系统结构。将该图与 图 2 进行比较,后者显示了 DB2 的系统结构。在阅读本文的时候,为便于理解,可以参照这两个图。
图 1. Oracle on Linux, UNIX, and Windows Version 10.2 的系统结构
图 1. Oracle on Linux, UNIX, and Windows Version 10.2 的系统结构

图 2. DB2 on Linux, UNIX, and Windows 系统结构
图 2. DB2 on Linux, UNIX, and Windows 系统结构


Continue reading “oracle与db2的区别比较(转)”