PHP二分查找法应用 之 IP查找

前段时间做数据分析,需要大量的IP地址查询(每秒钟近万次检索),首先考虑到使用数据库。数据库大概存储几十万条IP记录,记录集如下:

  这样做查询需要用到如下SQL:

  这样的检索显然用不到索引,即使用到,MySQL查询效率也不大可能达到每秒500次以上,我做了很多并发优化,最终平均查询效率也只有每秒200次左右,实在是头痛。一开始我也有想到借鉴纯真IP库的检索方法,但是我一直对算法有抵触,也以为二分法很难,所以就没有尝试使用,直到最后没有办法了,才最终实现了二分法的IP地址检索。
  从上表可以看到IP库是从0到4294967295的一个连续数值,这个数值要是拆开存储,会有几百G的数据,所以没办法使用索引也没办法哈希。最终我使用PHP将这些东东转为二进制存储,抛弃了数据库的检索。可以看到IP起止长度为一个4字节的长整型,后面的国家ID、省份ID等,可以使用2个字节的短整型来存储,总共一行数据就有18个字节,总共31万条数据,算起来也就5M的样子。具体IP库生成代码如下:
<?php

/*
IP文件格式:
3741319168 3758096383 182 0 0 0 0
3758096384 3774873599 3 0 0 0 0
3774873600 4026531839 182 0 0 0 0
4026531840 4278190079 182 0 0 0 0
4294967040 4294967295 312 0 0 0 0
*/
set_time_limit(0);
$handle = fopen(‘./ip.txt’, ‘rb’);
$fp = fopen("./ip.dat", ‘ab’);
if (
$handle) {
while (!
feof($handle)) {
$buffer = fgets($handle);
$buffer = trim($buffer);
$buffer = explode("\t", $buffer);
foreach (
$buffer as $key => $value) {
$buffer[$key] = (float) trim($value);
}
$str = pack(‘L’, $buffer[0]);
$str .= pack(‘L’, $buffer[1]);
$str .= pack(‘S’, $buffer[2]);
$str .= pack(‘S’, $buffer[3]);
$str .= pack(‘S’, $buffer[4]);
$str .= pack(‘S’, $buffer[5]);
$str .= pack(‘S’, $buffer[6]);
fwrite($fp, $str);
}
}

?>

这样IP就按照顺序每18字节一个单位排列了,所以很容易就使用二分法来检索出IP信息:

<?php
function getip($ip, $fp) {
fseek($fp, 0);
$begin = 0;
$end = filesize(‘./ip.dat’);
$begin_ip = implode(, unpack(‘L’, fread($fp, 4)));
fseek($fp, $end 14);
$end_ip = implode(, unpack(‘L’, fread($fp, 4)));
$begin_ip = sprintf(‘%u’, $begin_ip);
$end_ip = sprintf(‘%u’, $end_ip);

do {
if ($end $begin <= 18) {
fseek($fp, $begin + 8);
$info = array();
$info[0] = implode(, unpack(‘S’, fread($fp, 2)));
$info[1] = implode(, unpack(‘S’, fread($fp, 2)));
$info[2] = implode(, unpack(‘S’, fread($fp, 2)));
$info[3] = implode(, unpack(‘S’, fread($fp, 2)));
$info[4] = implode(, unpack(‘S’, fread($fp, 2)));
return
$info;
}

$middle_seek = ceil((($end $begin) / 18) / 2) * 18 + $begin;

fseek($fp, $middle_seek);
$middle_ip = implode(, unpack(‘L’, fread($fp, 4)));
$middle_ip = sprintf(‘%u’, $middle_ip);

if ($ip >= $middle_ip) {
$begin = $middle_seek;
} else {
$end = $middle_seek;
}
} while (
true);
}

?>

  以上$fp为打开ip.dat的文件句柄,由于是循环检索,所以写在函数外面,免得每次检索都要打开一次文件,30W行数据二分法最多也只需要循环7次(2^7)左右即可找到准确的IP信息。之后本来还想将ip.dat放在内存中加快检索速度,后来发现,字符串定位函数的效率,根本和文件指针的偏移定位不是在一个数量级的,所以还是放弃使用内存来存放IP库。
  这个实现,使IP检索效率提高了近百倍,只是一个简单的二分法的应用,从此算法在WEB应用中不重要的观念彻底打消了。其实要实现这个,我还请教了金狐,我一开始是请他帮我生成一个纯真格式的IP库,然后用Discuz的IP查询函数来检索,不过他不肯帮我,最后造就了我的这个实践和学习。有时候,求人不如求己。

PHP 中单一实例类的实现

有时候我们希望一个类在使用的时候只存在一个实例,但是我们又不敢保证自己不会在无意中new 了多次,怎么办呢?这里给出了一个保证单一实例类的一种做法:

<?php
// 单一实例的封装方法 
 /**
 * @author lijunjie <lijunjie1982@yahoo.com.cn> 
 * @date 2008-12-7 
 * @version 1.0 
 */ 
class OnlyOneInstance 

    private static 
$instance false

    private 
$instanceId 0

    public static function 
getInstance
() { 
        if(
OnlyOneInstance::$instance === false
) { 
            
OnlyOneInstance::$instance = new OnlyOneInstance
(); 
        } 
        return 
OnlyOneInstance::$instance

    } 
    
/// 私有的构造函数保证了该类无法在外部构造
    
private function __construct
(){
        
$this->_init
();
    }
    private function 
_init
() { 
        
$this->instanceId mt_rand
(); 
    } 
    public function 
say
() { 
        echo 
"my id is $this->instanceId\n"

    } 

OnlyOneInstance::getInstance()->say(); 
OnlyOneInstance::getInstance()->say
(); 

// 两次输出是一样的,说明两次的使用的是同一个实例 
exit;
?> 

 

shell 之 九九乘法表

为了学点Linux shell,无聊至极,用while写了个99乘法表:

i=1
while [ $i lt 10 
];do 
    
j=
1
    
while [ $j lt 10 
];do
        if [ 
$i ge $j ];
then
            
echo –
"$i * $j = $(($i * $j))"’ ‘
        
fi
        
((j
++))
    
done
    
echo
    ((
i
++))
done

你还别说,shell还真不是很好写呢

负载均衡的原理与算法介绍

转自:http://sites.google.com/site/star33375249/Home/database/mysql/fu-zai-jun-heng-de-yuan-li-yu-suan-fa-jie-shao

服务器负载均衡算法有很多(持续性的和非持续性的),包括轮循算法、最少连接算法、响应时间算法、散列算法、最少连接失误算法,链路带宽算法等等。此外实际服务器(Real Server)可以被分配不同的加权值来调整被分配的流量。比如性能高的大型服务器可配置较大的加权值,而为性能较低的小型服务器设置较小的加权值。为了避免服务器因过载而崩溃,可为实际服务器指定最大连接阈值来避免该服务器过载。任何服务器可被指定为另一台服务器的备份服务器或溢出服务器,从而进一步保证了应用可用性。

    非持续性算法(Non-Persistent):

一个客户端的不同的请求可能被分配到一个实际服务组中的不同的实服务器上进行处理。主要有轮循算法、最少连接算法、响应速度算法等。

    -轮循算法(Round Robin):

说明:

    每一次来自网络的请求轮流分配给内部中的每台服务器,从1至N然后重新开始。

举例:

    此种均衡算法适合于服务器组中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡的情况;

    -最少连接算法(Least Connection):

说明:

    客户端的每一次请求服务在服务器停留的时间都可能会有较大的差异,随着工作时间的加长,如果采用简单的轮循或随机均衡算法,每一台服务器上的连接进程可能会产生极大的不同,这样的结果并不会达到真正的负载均衡。最少连接数均衡算法对内部中有负载的每一台服务器都有一个数据记录,记录的内容是当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。

举例:此种均衡算法适合长时间处理的请求服务。

  -响应速度算法(Response Time):

说明:

    负载均衡设备对内部各服务器发出一个探测请求(例如Ping),然后根据内部中各服务器对探测请求的最快响应时间来决定哪一台服务器来响应客户端的服务请求。

举例:

    此种均衡算法能较好地反映服务器的当前运行状态,但最快响应时间仅仅指的是负载均衡设备与服务器间的最快响应时间,而不是客户端与服务器间的最快响应时间。

    持续性算法(Persistent):

 

    从一个特定的客户端发出的请求都被分配到一个实服务组中的同一个实服务器上进行处理。主要包括:

A.基于IP的算法

-Persistent IP (pi):基于用户IP地址来选择服务器。

-Hash IP (hi) :基于用户IP地址的HASH值,来选择服务器

-Consistent Hash IP (chi):

B.基于报头/请求的算法

-Hash Header (hh):基于用户请求报中HTTP报头来选择服务器;

-Persistent Hostname (ph) :基于用户请求报中HTTP报头的Hostname的HASH值,来选择服务器;

-Persistent URL (pu):基于对URI Tag 和值的静态对应关系来选择服务器。

-SSL Session ID (sslsid):基于SSL会话ID来选择服务器。

C.基于Cookie的算法

-Persistent Cookie (pc) : 选择服务器基于用户请求包用Cookie Name / Value 的静态对应关系;

-Hash Cookie (hc) :选择服务器基于用户请求包用Cookie Name / Value 的Hash 值对应关系;

-Insert Cookie (ic) :选择服务器基于负载均衡器 向服务器响应包中插入Cookie;

-Re-write Cookie (rc):选择服务器基于负载均衡器向服务器响应包中重写Cookie值。

(必须为重写指定Cookie值的偏移量)

windows 批处理脚本 之 for

首先,贴个帮助吧:

D:\>for /?
对一组文件中的每一个文件执行某个特定命令。

FOR %variable IN (set) DO command [command-parameters]

  %variable  指定一个单一字母可替换的参数。
  (set)      指定一个或一组文件。可以使用通配符。
  command    指定对每个文件执行的命令。
  command-parameters
             为特定命令指定参数或命令行开关。

在批处理文件中使用 FOR 命令时,指定变量请使用 %%variable
而不要用 %variable。变量名称是区分大小写的,所以 %i 不同于 %I.

如果命令扩展名被启用,下列额外的 FOR 命令格式会受到
支持:

FOR /D %variable IN (set) DO command [command-parameters]

    如果集中包含通配符,则指定与目录名匹配,而不与文件
    名匹配。

FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]

    检查以 [drive:]path 为根的目录树,指向每个目录中的
    FOR 语句。如果在 /R 后没有指定目录,则使用当前
    目录。如果集仅为一个单点(.)字符,则枚举该目录树。

FOR /L %variable IN (start,step,end) DO command [command-parameters]

    该集表示以增量形式从开始到结束的一个数字序列。
    因此,(1,1,5) 将产生序列 1 2 3 4 5,(5,-1,1) 将产生
    序列 (5 4 3 2 1)。

FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN ("string") DO command [command-parameters]
FOR /F ["options"] %variable IN (‘command’) DO command [command-parameters]

    或者,如果有 usebackq 选项:

FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN ("string") DO command [command-parameters]
FOR /F ["options"] %variable IN (‘command’) DO command [command-parameters]

    filenameset 为一个或多个文件名。继续到 filenameset 中的
   下一个文件之前,每份文件都已被打开、读取并经过处理。
    处理包括读取文件,将其分成一行行的文字,然后将每行
    解析成零或更多的符号。然后用已找到的符号字符串变量值
    调用 For 循环。以默认方式,/F 通过每个文件的每一行中分开
    的第一个空白符号。跳过空白行。您可通过指定可选 "options"
    参数替代默认解析操作。这个带引号的字符串包括一个或多个
    指定不同解析选项的关键字。这些关键字为:

        eol=c           – 指一个行注释字符的结尾(就一个)
        skip=n          – 指在文件开始时忽略的行数。
        delims=xxx      – 指分隔符集。这个替换了空格和跳格键的
                          默认分隔符集。
        tokens=x,y,m-n  – 指每行的哪一个符号被传递到每个迭代
                          的 for 本身。这会导致额外变量名称的分配。m-n
                          格式为一个范围。通过 nth 符号指定 mth。如果
                          符号字符串中的最后一个字符星号,
                          那么额外的变量将在最后一个符号解析之后
                          分配并接受行的保留文本。
        usebackq        – 指定新语法已在下类情况中使用:
                          在作为命令执行一个后引号的字符串并且一个单
                          引号字符为文字字符串命令并允许在 filenameset
                          中使用双引号扩起文件名称。

    某些范例可能有助:

FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k

    会分析 myfile.txt 中的每一行,忽略以分号打头的那些行,将
    每行中的第二个和第三个符号传递给 for 程序体;用逗号和/或
    空格定界符号。请注意,这个 for 程序体的语句引用 %i 来
    取得第二个符号,引用 %j 来取得第三个符号,引用 %k
    来取得第三个符号后的所有剩余符号。对于带有空格的文件
    名,您需要用双引号将文件名括起来。为了用这种方式来使
    用双引号,您还需要使用 usebackq 选项,否则,双引号会
    被理解成是用作定义某个要分析的字符串的。

    %i 专门在 for 语句中得到说明,%j 和 %k 是通过
    tokens= 选项专门得到说明的。您可以通过 tokens= 一行
    指定最多 26 个符号,只要不试图说明一个高于字母 ‘z’ 或
    ‘Z’ 的变量。请记住,FOR 变量是单一字母、分大小写和全局的;而且,
    同时不能有 52 个以上都在使用中。

    您还可以在相邻字符串上使用 FOR /F 分析逻辑;方法是,
    用单引号将括号之间的 filenameset 括起来。这样,该字符
    串会被当作一个文件中的一个单一输入行。

    最后,您可以用 FOR /F 命令来分析命令的输出。方法是,将
    括号之间的 filenameset 变成一个反括字符串。该字符串会
    被当作命令行,传递到一个子 CMD.EXE,其输出会被抓进
    内存,并被当作文件分析。因此,以下例子:

      FOR /F "usebackq delims==" %i IN (set) DO @echo %i

    会枚举当前环境中的环境变量名称。

另外,FOR 变量参照的替换已被增强。您现在可以使用下列
选项语法:

     ~I         – 删除任何引号("),扩充 %I
     %~fI        – 将 %I 扩充到一个完全合格的路径名
     %~dI        – 仅将 %I 扩充到一个驱动器号
     %~pI        – 仅将 %I 扩充到一个路径
     %~nI        – 仅将 %I 扩充到一个文件名
     %~xI        – 仅将 %I 扩充到一个文件扩展名
     %~sI        – 扩充的路径只含有短名
     %~aI        – 将 %I 扩充到文件的文件属性
     %~tI        – 将 %I 扩充到文件的日期/时间
     %~zI        – 将 %I 扩充到文件的大小
     %~$PATH:I   – 查找列在路径环境变量的目录,并将 %I 扩充
                   到找到的第一个完全合格的名称。如果环境变量名
                   未被定义,或者没有找到文件,此组合键会扩充到
                   空字符串

可以组合修饰符来得到多重结果:

     %~dpI       – 仅将 %I 扩充到一个驱动器号和路径
     %~nxI       – 仅将 %I 扩充到一个文件名和扩展名
     %~fsI       – 仅将 %I 扩充到一个带有短名的完整路径名
     %~dp$PATH:i – 查找列在路径环境变量的目录,并将 %I 扩充
                   到找到的第一个驱动器号和路径。
     %~ftzaI     – 将 %I 扩充到类似输出线路的 DIR

在以上例子中,%I 和 PATH 可用其他有效数值代替。%~ 语法
用一个有效的 FOR 变量名终止。选取类似 %I 的大写变量名
比较易读,而且避免与不分大小写的组合键混淆。

D:\>

只看帮助可能还是不明白,再给几个例子:

1. 打印指定目录下的所有文件

D:\>for %i in (e:\*) do @echo %i
e:\101ThingsToKnowAboutSingleSignOn.pdf
e:\3-IT168单点登录系统数据库结构说明.doc
e:\FTP.cab
e:\login.do
e:\mysql_connect

2. 打印指定目录下的所有目录

D:\>for /D %i in (e:\*) do @echo %i
e:\demo
e:\help
e:\My Document
e:\Mycmd

3. 递归打印指定目录下的文件

D:\>for /R %i in (e:\) do @echo %i

4. 递归打印指定目录下的目录

D:\>for /R /D %i in (e:\) do @echo %i

5. 循环数字

D:\>for /L %i in (1,1,10) do @echo %i
1
2
3
4
5
6
7
8
9
10

6. 处理文件内容

待续。。。

curl 中文简介

原文地址:http://www.donews.net/sogoo/articles/385625.aspx

CURL? 嗯,说来话长了~~~~

这东西现在已经是苹果机上内置的命令行工具之一了,可见其魅力之一斑

1)
二话不说,先从这里开始吧!

curl http://www.yahoo.com

回车之后,www.yahoo.com 的html就稀里哗啦地显示在屏幕上了~~~~~

2)
嗯,要想把读过来页面存下来,是不是要这样呢?
curl http://www.yahoo.com > page.html

当然可以,但不用这么麻烦的!
用curl的内置option就好,存下http的结果,用这个option: -o
curl -o page.html http://www.yahoo.com

这样,你就可以看到屏幕上出现一个下载页面进度指示。等进展到100%,自然就OK咯

3)
什么什么?!访问不到?肯定是你的proxy没有设定了。
使用curl的时候,用这个option可以指定http访问所使用的proxy服务器及其端口: -x
curl -x 123.45.67.89:1080 -o page.html http://www.yahoo.com

4)
访问有些网站的时候比较讨厌,他使用cookie来记录session信息。
像IE/NN这样的浏览器,当然可以轻易处理cookie信息,但我们的curl呢?…..
我们来学习这个option: -D <– 这个是把http的response里面的cookie信息存到一个特别的文件中去
curl -x 123.45.67.89:1080 -o page.html -D cookie0001.txt http://www.yahoo.com

这样,当页面被存到page.html的同时,cookie信息也被存到了cookie0001.txt里面了

5)
那么,下一次访问的时候,如何继续使用上次留下的cookie信息呢?要知道,很多网站都是靠监视你的cookie信息,
来判断你是不是不按规矩访问他们的网站的。
这次我们使用这个option来把上次的cookie信息追加到http request里面去: -b
curl -x 123.45.67.89:1080 -o page1.html -D cookie0002.txt -b cookie0001.txt http://www.yahoo.com

这样,我们就可以几乎模拟所有的IE操作,去访问网页了!

6)
稍微等等~~~~~我好像忘记什么了~~~~~
对了!是浏览器信息~~~~

有些讨厌的网站总要我们使用某些特定的浏览器去访问他们,有时候更过分的是,还要使用某些特定的版本~~~~
NND,哪里有时间为了它去找这些怪异的浏览器呢!?

好在curl给我们提供了一个有用的option,可以让我们随意指定自己这次访问所宣称的自己的浏览器信息: -A
curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -x 123.45.67.89:1080 -o page.html -D cookie0001.txt http://www.yahoo.com

这样,服务器端接到访问的要求,会认为你是一个运行在Windows 2000上的IE6.0,嘿嘿嘿,其实也许你用的是苹果机呢!

而"Mozilla/4.73 [en] (X11; U; Linux 2.2; 15 i686"则可以告诉对方你是一台PC上跑着的Linux,用的是Netscape 4.73,呵呵呵

7)
另外一个服务器端常用的限制方法,就是检查http访问的referer。比如你先访问首页,再访问里面所指定的下载页,这第二次访问的referer地址就是第一次访问成功后的页面地址。这样,服务器端只要发现对下载页面某次访问的referer地址不 是首页的地址,就可以断定那是个盗连了~~~~~

讨厌讨厌~~~我就是要盗连~~~~~!!
幸好curl给我们提供了设定referer的option: -e
curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -x 123.45.67.89:1080 -e "mail.yahoo.com" -o page.html -D cookie0001.txt http://www.yahoo.com

这样,就可以骗对方的服务器,你是从mail.yahoo.com点击某个链接过来的了,呵呵呵

8)
写着写着发现漏掉什么重要的东西了!—– 利用curl 下载文件

刚才讲过了,下载页面到一个文件里,可以使用 -o ,下载文件也是一样。
比如, curl -o 1.jpg http://cgi2.tky.3web.ne.jp/~zzh/screen1.JPG
这里教大家一个新的option: -O
大写的O,这么用: curl -O http://cgi2.tky.3web.ne.jp/~zzh/screen1.JPG
这样,就可以按照服务器上的文件名,自动存在本地了!

再来一个更好用的。
如果screen1.JPG以外还有screen2.JPG、screen3.JPG、….、screen10.JPG需要下载,难不成还要让我们写一个script来完成这些操作?
不干!
在curl里面,这么写就可以了:
curl -O http://cgi2.tky.3web.ne.jp/~zzh/screen[1-10].JPG

呵呵呵,厉害吧?!~~~

9)
再来,我们继续讲解下载!
curl -O http://cgi2.tky.3web.ne.jp/~{zzh,nick}/[001-201].JPG

这样产生的下载,就是
~zzh/001.JPG
~zzh/002.JPG

~zzh/201.JPG
~nick/001.JPG
~nick/002.JPG

~nick/201.JPG

够方便的了吧?哈哈哈

咦?高兴得太早了。
由于zzh/nick下的文件名都是001,002…,201,下载下来的文件重名,后面的把前面的文件都给覆盖掉了~~~

没关系,我们还有更狠的!
curl -o #2_#1.jpg http://cgi2.tky.3web.ne.jp/~{zzh,nick}/[001-201].JPG

–这是…..自定义文件名的下载?
–对头,呵呵!

#1是变量,指的是{zzh,nick}这部分,第一次取值zzh,第二次取值nick
#2代表的变量,则是第二段可变部分—[001-201],取值从001逐一加到201
这样,自定义出来下载下来的文件名,就变成了这样:
原来: ~zzh/001.JPG —> 下载后: 001-zzh.JPG
原来: ~nick/001.JPG —> 下载后: 001-nick.JPG

这样一来,就不怕文件重名啦,呵呵

9)
继续讲下载
我们平时在windows平台上,flashget这样的工具可以帮我们分块并行下载,还可以断线续传。
curl在这些方面也不输给谁,嘿嘿

比如我们下载screen1.JPG中,突然掉线了,我们就可以这样开始续传
curl -c -O http://cgi2.tky.3wb.ne.jp/~zzh/screen1.JPG

当然,你不要拿个flashget下载了一半的文件来糊弄我~~~~别的下载软件的半截文件可不一定能用哦~~~

分块下载,我们使用这个option就可以了: -r
举例说明
比如我们有一个http://cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 要下载(赵老师的电话朗诵 😀 )
我们就可以用这样的命令:
curl -r 0-10240 -o "zhao.part1" http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 &\
curl -r 10241-20480 -o "zhao.part1" http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 &\
curl -r 20481-40960 -o "zhao.part1" http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3 &\
curl -r 40961- -o "zhao.part1" http:/cgi2.tky.3web.ne.jp/~zzh/zhao1.mp3

这样就可以分块下载啦。
不过你需要自己把这些破碎的文件合并起来
如果你用UNIX或苹果,用 cat zhao.part* > zhao.mp3就可以
如果用的是Windows,用copy /b 来解决吧,呵呵

上面讲的都是http协议的下载,其实ftp也一样可以用。
用法嘛,
curl -u name:passwd ftp://ip:port/path/file
或者大家熟悉的
curl ftp://name:passwd@ip:port/path/file

10)
说完了下载,接下来自然该讲上传咯
上传的option是 -T

比如我们向ftp传一个文件: curl -T localfile -u name:passwd ftp://upload_site:port/path/

当然,向http服务器上传文件也可以
比如 curl -T localfile http://cgi2.tky.3web.ne.jp/~zzh/abc.cgi
注意,这时候,使用的协议是HTTP的PUT method

刚才说到PUT,嘿嘿,自然让老服想起来了其他几种methos还没讲呢!
GET和POST都不能忘哦。

http提交一个表单,比较常用的是POST模式和GET模式

GET模式什么option都不用,只需要把变量写在url里面就可以了
比如:
curl http://www.yahoo.com/login.cgi?user=nickwolfe&password=12345

而POST模式的option则是 -d

比如,curl -d "user=nickwolfe&password=12345" http://www.yahoo.com/login.cgi
就相当于向这个站点发出一次登陆申请~~~~~

到底该用GET模式还是POST模式,要看对面服务器的程序设定。

一点需要注意的是,POST模式下的文件上的文件上传,比如
<form method="POST" enctype="multipar/form-data" action="http://cgi2.tky.3web.ne.jp/~zzh/up_file.cgi">
<input type=file name=upload>
<input type=submit name=nick value="go">
</form>
这样一个HTTP表单,我们要用curl进行模拟,就该是这样的语法:
curl -F upload=@localfile -F nick=go http://cgi2.tky.3web.ne.jp/~zzh/up_file.cgi

罗罗嗦嗦讲了这么多,其实curl还有很多很多技巧和用法
比如 https的时候使用本地证书,就可以这样
curl -E localcert.pem https://remote_server

再比如,你还可以用curl通过dict协议去查字典~~~~~
curl dict://dict.org/d:computer

今天就先讲到这里吧,呵呵。疯狂的curl功能,需要你—一起来发掘。

copyright by nickwolfe@CCF
2004.08.24 21:24

相关链接:

字典协议的rfc:http://tools.ietf.org/html/rfc2229

字典协议服务器列表:http://luetzschena-stahmeln.de/dictd/index.php

路由检查脚本

对于一个大网络来讲,一般都有内网,有内网就有复杂的路由问题,一个机器要和很多其它机器通信,往往需要在机器上添加大量的路由,到一定程度,连自己都不知道那些路由有效,那些路由无效了,下面给出一个检查路由的php脚本:

<?php
// filename: checkroute.php
// check route use ping command
// eg : route -n | egrep -v "IP|De|0\.0\.0\.0" |cut -d " " -f 1 | php checkroute.php
$arropt getopt("f:v"
);
if(isset(
$arropt[‘f’
])) {
    if(!(
$fp fopen($arropt[‘f’],‘r’
))){
        die(
"open file $f error\n"
);
    }
} else {
    
$fp STDIN
;
}
$debug false
;
if(isset(
$arropt[‘v’])) $debug true

while(!feof($fp)) {
    
$line trim(fgets($fp
));
    if(
$line == 
) continue;
    
$ip preg_replace("/\.0$/",".1",$line
);
    
$cmd "/bin/ping -c 1 -W 1 $ip 2>1 >/dev/null"
;
    
debug($cmd
);    
    
$result = @exec($cmd,$arr_ret,$retcode
);
    if(
$retcode != 0
){
        echo 
$line."\n"
;
    }
}

function debug($msg) {
    global 
$debug

    if(
$debug
) {
        echo 
$msg."\n"
;
    }
}
?>

关于keepalive的解释

Apache配置文件中有三个关于KeepAlive的配置指令:
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15

一般来讲,http请求是一次请求完毕就关闭连接的,但是有些时候,一个apache只有少数的固定的几个或几十个机器频繁的访问,这时,每次访问都重新建立tcp连接,感觉有些无聊,这时就用到KeepAlive的相关设置了:
KeepAlive 为 On,如果http请求头明确说明:Connection:keep-alive ;则一次请求结束后,如果该连接使用的次数没有超过MaxKeepAliveRequests ,服务器并不立即主动断开连接,而是等待KeepAliveTimeout 指定的时间,这时,如果客户端没有再发起http请求,则关闭连接;如果在KeepAliveTimeout时间内,客户端又使用该连接做http请求,则省去了重新建立tcp连接的消耗了。

就上面的设置而言:

———————————-

如果客户端发送http请求头:


Connection:keep-alive

则服务器端相应的http头为:


Keep-Alive: timeout=15, max=100
Connection: Keep-Alive

————————————

如果客户端发送http请求头:


Connection:close

则服务器端响应的http头为:


Connection:close

并且服务器端主动关闭连接

================================================

如果服务器端设置为:KeepAlive Off

则不管客户端的http请求头如何设置,服务器端总是每次连接只处理一个请求,并立即主动关闭,响应的http头为:


Connection:close

———————————————-

下面附一段代码:

<?php
main
();
function 
main() {
    
$host "ljj.com";
    
$port 80;
    
$url "/";
    
$fp fsockopen($host$port ,$errno$errstr10);
    if(
$fp === false) {
        die(
$errstr);
    }
    
$str "GET / HTTP/1.1\nHost: ljj.cn\nConnection:keep-alive\n\n";
    
$i 0;
    while(
$i++ < 3) {
        
$len fputs($fp,$str);
        if(
$len === false) { // 这里这么判断是没有用的,因为如果服务器端单向关闭,该连接没有完全断开,则还是可以写数据的,只是没有响应而已
            
die("fp error\n");
        }
        
$out fread($fp,2048);
        echo 
"$i:$out\n";
    }
    
fclose($fp);
}

?>

这段代码说明了多次请求可以使用同一条连接(在服务器端KeepAlive On的情况下

VMWARE序列号大全

【VMWARE序列号大全】 
=====VMware Workstation4.5.2 Build 8848 for Windows===== 

ZHDH1-UR90N-W844G-4PTN6 

G1NP0-T88AL-M016F-4P8N2 

=====VMware-workstation-4.5.2-8848 for Linux ===== 

ZC14J-4U16A-0A04G-4MEZP 

J1WF8-58LDE-881DG-4M8Q3 

=====VMware Workstation 5 For Windows ===== 

LUXRM-WP0DN-A256U-4M9Q3 

DJXDR-NDT27-Y2NDU-4YTZK 

=====VMware Workstation 5 for Linux ===== 

DA925-HP80U-Z8HDC-4WXXP 

3KW2W-AYR2C-88M6F-4MDQ2 

=====VMware.GSX.Server.3.1.0-9089.for.Windows===== 

98XY4-54VA4-4216V-4PDZ6 

WH0M5-XW50J-WA4FU-4MTZ3 

=====VMware-gsx-server-3.1.0-9089.for Linux===== 

N218N-NR66R-F0JDF-4P9NP 

H2W8H-X82DC-J8N6G-4M9Q6 

=====VMWare ESX Server 2.x===== 

0VHD0-0P86V-0C0AH-4018N 
SMP 0KR08-02CAH-0DJ2H-48124 

02M8R-0HA2N-0CK8M-42JAN 
SMP 0AMDE-0UWFP-0E601-42J84 

=====VMware Ace 1.0.0===== 

admin:8H18E-8U505-HA14Z-4P8QL 

RCT0X-XHN8U-H20FY-4W9ZP 

player:WC94X-3H90R-K05DU-4MTN3 

DHHF8-K0P6P-Z25DY-4YENK 

workstation:TKN8T-1UD2Q-70N4C-4YXXQ 


AJMMN-3YUDP-8ANFG-4WWX2 

=====VMware VirtualCenterV1.2.0===== 


点击浏览该文件 

VC管理GSX的SN: 

QU9HW-NM5FT-VAJ4G-5W9N3 

VHM05-U0Q27-E0HFA-5WRXL 

virtualcenter 最全和最强的license 


virtualcenter : 921H4-7WR4V-T2NDC-5YDZK 

vmotion : 8VN44-Q8PD9-P0NFY-5PWZL 

esx: XL584-9PH2Z-02H4C-5P9XL 

gsx: EH8M0-5RP8Y-M804F-5MRN3 

=====VMware.P2V.Assistant.v2.0.0===== 

L80ME-56Q6F-U8M4F-5WEQQ 

4KE0R-0A04Q-H05DZ-5WEZL

什么是线程安全

版权声明:如有转载请求,请注明出处:http://blog.csdn.net/yzhz 杨争

1、什么是线程安全(thread safe)?
        一个类要成为线程安全的类,就是在该类被多个线程访问时,不管运行环境中执行这些线程有什么样的时序安排或者交错,它仍然执行正确行为,并且在调用的代码中没有任何额外的同步。

2、什么时候考虑线程安全问题?
       当一个类的实例为singleton的时候,你就要考虑该实例在调用的时候是否是线程安全的。
       最熟悉的例子就是servlet, 每个servlet在servlet engineer中只有一个实例。除非它实现SingleThreaded接口。所以我们一般要求在servlet中不要定义成员变量,以避免线程不安全。
       是不是凡是singleton的对象都不是线程安全的呢?答案是No。准确的表达应该是:只有该类中定义了有状态的成员时该类才是线程不安全的
举个例子:
public class A{
    String id ;
    public void process(){
       print(id);
       …
    }
}
       id是一个有状态的变量。什么是有状态,就是指每次调用该类的时候如果该id值可能存在不同的值,那么这个id就是有状态的。

我们再看看下面的例子。
public class B{
    public void process(){
     int i;
     int j;
          
     println(i*y);
    }
}
        这个class B在单实例的情况下就是线程安全的。原因是:该类没有有状态的成员。i,j是局部变量,某个线程都会有自己的stack保存这些局部变量。所以对于不同线程来说,这些变量是相互不影响的。

        对于存在线程不安全的类,如何避免出现线程安全问题呢?
1、采用synchronized同步。缺点就是存在堵塞问题。
2、使用ThreadLocal(实际上就是一个HashMap),这样不同的线程维护自己的对象,线程之间相互不干扰。

总结:
1、我们一般要求商业逻辑的BO为线程安全的类,这样就可以将该BO创建成一个单实例的对象,提高访问的效率。为了使BO为线程安全的对象,我们所要做的很简单,就是该类中不要有与状态相关的成员变量。