管道与队列

相同点

1. 都是先进先出

不同点:

1. 管道可以以只读方式打开,但不能以只写方式打开;因为管道是不存储数据的



如何用Linux系统中的fifo来实现队列:

消费者a.php:
$fp = fopen("/dev/shm/fifo1","w+");
while(!
feof($fp)) {

        echo fgets($fp);
        sleep(4);

}

生产者b.php:
$fp = fopen("/dev/shm/fifo1","w+");
$pid = posix_getpid();
while(
1) {

$str = $pid."_".time()."n";
        fwrite($fp,$str);
        echo $str;
        sleep(2);

}

注意:
1. 不管是生产者还是消费者都要以读写的方式打开;否则:
生产者如果以只写方式打开,会因为没有消费者而在打开时阻塞;
消费者如果以只读方式打开,消费完就退出了,不会阻塞,达不到随时服务的效果。

2. 因为文件总是有4096字节的IO Block,所以管道里可以阻塞4096字节的数据;就是说,如果消费者进程仅仅是打开了fifo,但是没有读取,这时生产者可以写入最多4096字节的数据(这个4096和生产者进程的buffer无关,是文件本身的一个属性,不知道怎么修改),和写入进程的多少没有关系,一旦阻塞了4096字节的数据,任何欲写入(可能还没写一个字节呢)的进程都会被阻塞或直接返回失败。

3. 注意下面情况:
1) A进程打开某fifo1,开始循环读取
2) 删除fifo1, 这时A进程是不知道的,并且不会发生错误
3) B进程创建同样的fifo1,开始写fifo1, 这时A进程是读取不到B进程写入的数据的,必须重新打开
   解决办法: 还没有呢

4. 如果消费者进程没有启动,则生产者进程写入多少丢弃多少

5. 如果有一个消费者进程,多个生产者进程,则任何一个生产者进程退出,消费者进程都将读到一个文件结束符,所以这种情况不能在读取到文件结束符时退出,而是读到文件结束符时丢弃,继续读取(没有数据时会阻塞的)。

6. 如果不小心将fifo创建成了一般文件,则后果就难以预测了。

7. 如果想以非阻塞的方式来读取一个fifo中的数据,则需要:
   a. 以读写的方式打开(注意要有写权限才行哦)
   b. 对打开的流做nonblock的设置,php里面的语法为: stream_set_blocking($fp, 0);

我需要一个队列:
1. 没有网络开销和磁盘IO的开销,只需要内存就可以
2. 允许在数据处理太慢时丢失旧数据,因为对我来说,过期的数据是没有意义的
3.

location.replace在Firefox和IE下的小区别

写了一个脚本,内容为:
<script>
location.replace("");
</script>

该脚本在Firefox下死循环了,在IE下定向到网站的根目录了。
说明Firefox认为空就是自己,IE认为空就是根。

用302跳转试试,写脚本如下:
<?php
head("Location: ");
?>

Firefox下和没有该Location头一样,没有循环也没有跳转;
IE下还是跳转到网站的根目录了。

关于json编码解码的问题

其实json编码解码应该是一件很简单的事情,提供的类或库函数用起来也就是encode、decode,似乎不是一件很复杂的事情;但随着json的 使用的越来越多,还真就发现了一些不能不去注意的问题。

1.   含有自引用属性的类的encode和decode
       在js中, {"me":this} 是一个合法的对象,但是PHP对该对象做decode时,结果是: NULL
       在PHP中:
<?php
class test {
    public 
$a;
    
// 注意: 不能直接写为:
    // public $a = $this;
    
public function __construct() {
        
$this->$this;
    }
}
?>

test是一个合法的类,但是PHP对该对象做encode时,结果:
Warning: json_encode(): recursion detected in E:\home\desktop\test.php on line 26
{"a":{"a":null}}

2.  单引号的问题, key、value最好使用双引号来引
$obj json_decode('{"me":"this"}');  // 属性和值都是用双引号
var_dump($obj);

结果:
object(stdClass)#2 (1) {
  ["me"]=>
  string(4) "this"
}

$obj json_decode("{'a':'this'}");  // 属性和值都是用单引号
var_dump($obj);

结果: NULL

使用Services_JSON 倒是没有问题的
$json = new Services_JSON();
var_dump($json->decode("{'a':'this'}"));
exit;

输出:
object(stdClass)#2 (1) {
  ["a"]=>
  string(4) "this"
}

3.  特殊字符的转移问题
对于双引号、斜线、反斜线是需要转义的

今天重新了解了json这个东西,仔细解读了: http://json.org/  ,特别是里面的图的理解。

bat 脚本实例

1. for循环

循环数字:
@echo off
FOR /L %i IN (1,1,10) DO echo %i
#rem 输出 1 2 3 … 10

FOR %i IN (1,1,10) DO echo %i
#rem 输出 1 1 10


匹配当前目录下的所有文件(不包含子目录):
for %i in (*) do echo %i

匹配d:\ 目录下的js文件(遍历子目录):
for  /R d:\ %i in (*.js) do echo %i

循环目录(
不包含子目录),不包含文件:
for /D %i in (*) do echo %i

循环文件中的内容(按行分析):
for /F %i in (a.txt) do echo %i
#rem /F 说明set 是文件名

2.

登录解决方案

简单地说,登录就是输入用户名、密码,点击登录按钮就行了;但是到现在为止,我做登录已经两年了,如果真的这么简单,我这两年真就白活了;
其实,登录里面也有很多学问呢,做登录我们要考虑很多安全方面的问题,如:
一、防止扫密码
二、防止cookie被盗
三、防止密码被盗

每一个问题都很难做到像数学里描述一个逻辑那样的严谨,否则用户就必须符合很多条件才能上网了。

我们这里先讨论一下登录的问题,首先登录面临两个问题:
一、密码不能明文传输
二、登录使用的请求信息不能被截获,或者说即使被截获也不能使用

要解决这两个问题,下面给出几个解决方案:
一、使用https
登录

   优点: 只需要修改一下协议,就可以解决两个问题,做起来比较简单
   缺点:
         1. https 需要购买证书,是要花钱的,每年大概3000~10000不等
         2. 不是所有的客户端都只是https的
         3. 如果客户端的时间差的太多,也是无法访问https的
         4. 证书吊销列表的下载也影响登录的速度
         5. 浏览器对https有很多的安全限制,使得https和http之间的切换可能会有警告对话框
         6. 。。。

二、 使用login ticket的方式

   1. 提交用户名、密码之前先从服务器获取一个登录使用的票据lt,以lt为key存到mc里面吧
   2. 使用username=xxx&password=md5(password+lt)&lt=xxx 登录
   3. 根据lt查mc,如果存在,在根据username取password,做md5后比较;如果lt不存在,则该请求视为过期或重复请求

   优点:
      1. 不需要使用https
   缺点:
      1. 多一次请求
      2. 客户端需要做md5的代码,md5.js 压缩后也6k多了


三、 使用nonce的方式

   1. 使用username=xxx&password=md5(password+nonce)&nonce=yyyyy&timestamp=time_of_client_now 登录
   2. 服务器端的检查过程:
      if (timestamp + 5mins < server_time_now && md5(username+nonce) not in mc && 检查密码 && 将md5(username+nonce) 写入mc) 登录成功 else 登录失败
  
   优点:
      a. 一次请求就可以完成
      
   缺点:
      a. 对客户端的时间要求比较苛刻,不允许客户端时间比服务器快,不允许客户端比服务器时间慢超过5分钟

   该方式适用的情况: 客户端和服务器基本保证时钟同步


四、 该方式是二、三的结合

   1. 提交用户名、密码之前先获取一下服务器的时间timestamp
   2. 使用username=xxx&password_md5=md5(password+timestamp)&timestamp=time_of_server_now 登录
   3. 服务器端的检查过程同三、2.

  
优点:
1. 与二相比,第一次请求不需要写mc,实际登录成功之后才写mc

        


javascript 点滴

// eval 函数和new Function的上下文环境:
// eval()函数入口参数中指定的字符串总是被作为当前函数上下文中的语句来执行
// new Function() 中传入的字符串总是被作为一个全局的、匿名函数闭包中的语句行被执行
//  

eval("var a = 'global';");  // 声明一个全局的变量a
var obj = {};
(function (){

this.func = function() {
            eval("var a = 'internal';"); // 这里没有覆盖全局的变量a
            console.log("internal func:"+a); // 这里打印的a的值为 internal
            new Function("console.log('new Function:'+a);")();   // 这里打印的a的值为 global
            window.eval("alert(a);");  // 这里在IE和Firefox中表现不同,IE中认为是internal,Firefox中认为是global
    };

}).call(obj);

obj.func();
console.log("global:"+a);   // 这里打印的a的值为 global

// 使用eval获取对象直接量的方法,如:

var aobj = eval("{'a':'A','b':'B'}");  
这种写法是错误的,因为参数字符串没有被理解为一个对象,而是被理解为一个符合语句;然而作为一个符合语句,这里是有语法错误的,所以执行错误,正确的写法为:
var aobj = eval("({'a':'A','b':'B'})");

不过在jscript中存在一个例外:函数直接量(这里指匿名函数)不能通过这种方式来获得,例:

var func = eval('(function(){})');
alert(typeof func); // 输出为undefined

这种情况下,可以用具名函数来得到,例:
var func;
eval(
'function func(){}');

alert(typeof func); // 输出为 function

但是你可能遇到必须使用匿名函数的情况(不打算使用上例那样确定的函数名),这时就需要稍微复杂一些的代码(使用表达式运算),例:

// var func = eval('(function(){}).prototype.constructor');
// var func = eval('({$:function(){}}).$');
// var func = eval('[function(){}][0]');
...

javascript复制功能的实现

        

  1. /** 
  2.     

  3.  * 复制代码,支持IE/Firefox/NS 
  4.     

  5.  */  
  6.     

  7. function copyToClipboard(txt) {  
  8.     

  9.     if (window.clipboardData) {  
  10.     

  11.         window.clipboardData.clearData();  
  12.     

  13.         window.clipboardData.setData("Text", txt);  
  14.     

  15.     } else if (navigator.userAgent.indexOf("Opera") != -1) {  
  16.     

  17.         window.location = txt;  
  18.     

  19.     } else if (window.netscape) {  
  20.     

  21.         try {  
  22.     

  23.             netscape.security.PrivilegeManager  
  24.     

  25.                     .enablePrivilege("UniversalXPConnect");  
  26.     

  27.         } catch (e) {  
  28.     

  29.             alert("你使用的FireFox浏览器,复制功能被浏览器拒绝!\n请在浏览器地址栏输入“about:config”并回车。\n然后将“signed.applets.codebase_principal_support”双击,设置为“true”");  
  30.     

  31.             return;  
  32.     

  33.         }  
  34.     

  35.         var clip = Components.classes[‘@mozilla.org/widget/clipboard;1’]  
  36.     

  37.                 .createInstance(Components.interfaces.nsIClipboard);  
  38.     

  39.         if (!clip)  
  40.     

  41.             return;  
  42.     

  43.         var trans = Components.classes[‘@mozilla.org/widget/transferable;1’]  
  44.     

  45.                 .createInstance(Components.interfaces.nsITransferable);  
  46.     

  47.         if (!trans)  
  48.     

  49.             return;  
  50.     

  51.         trans.addDataFlavor(‘text/unicode’);  
  52.     

  53.         var str = new Object();  
  54.     

  55.         var len = new Object();  
  56.     

  57.         var str = Components.classes["@mozilla.org/supports-string;1"]  
  58.     

  59.                 .createInstance(Components.interfaces.nsISupportsString);  
  60.     

  61.         var copytext = txt;  
  62.     

  63.         str.data = copytext;  
  64.     

  65.         trans.setTransferData("text/unicode", str, copytext.length * 2);  
  66.     

  67.         var clipid = Components.interfaces.nsIClipboard;  
  68.     

  69.         if (!clip)  
  70.     

  71.             return false;  
  72.     

  73.         clip.setData(trans, null, clipid.kGlobalClipboard);  
  74.     

  75.     }  
  76.     


  77.     

javascript数组之奇怪用法

今天用到javascript的数组时,发现一个非常见的写法:

var arr = ['a','b','c'];
for (
i in arr) {
      
console.log("tag"+i);
      
console.log(arr.push(i));  // 期望: 我也不知道这将会输出什么
}
输出结果:

tag0
4
tag1
5
tag2
 6


var
arr = ['a','b','c'];
for (
i in arr) {
      
console.log(arr.pop());  // 期望: c b a
}

输出结果:

c
b

不知道怎么解释这种现象,基本应该是数组本身也有一个指针,for语句和pop、push操作都在同时使用该指针,于是结果就不像我们想象的那样了。

var arr = ['a','b','c'];
for (
i in arr) {
   
delete arr[i];  // 注意理解delete 的含义
}

console.log(arr);  // 期望: []

输出结果:
[undefined, undefined, undefined]