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为线程安全的对象,我们所要做的很简单,就是该类中不要有与状态相关的成员变量。

iptables下udp穿越结尾篇—-iptables和socks5

文章标题 iptables下udp穿越结尾篇—-iptables和socks5
张贴者: shixudong (member)
张贴日期 10/31/04 10:36 PM
iptables和socks5
从“iptables和natcheck”一文可知,只要在两端都采用了iptables作NAT后,即使两侧都通过了natcheck的兼容性测试,但iptables两侧永远也不能互相穿越。
怎么办呢,一种办法是在公网上添加中转服务器,两侧内网机器之间的UDP通讯都由中转服务器来中转(其实只要中转一侧足矣)。这种方法的好处是,因为中转服
务器在公网,所有NAT后面的机器都能和中转服务器建立连接,也就是说,不同内网之间的机器总是能通过中转服务器实现双向通信的。然而,该办法的缺点
是,对中转服务器的需求比较高,包括CPU处理能力和网络带宽两方面,而且客户机之间的通讯延迟也是不可避免的(目前网上最为盛行的Skype是个例外,
他采用了分布式中转技术,直接挂在互连网上不在防火墙后面的Skype客户端都能为他人提供中转服务,因此Skype在提供非常高呼叫成功率的同时还能确
保超高质量的语音效果)。更有一个更为重要的因素,即中转服务器的标准不统一,导致每种不同类型的P2P程式都需要一个专用的中转服务器。倘若这些中转服
务器之间不能做到资源共享的话,必然存在资源浪费现象(标准的中转协议似乎正在推出,名称为Traversal Using Relay NAT
即TURN)。
另一种比较好的办法就是采用Socks5(Rfc1928)代理服务器取代专用的中转服务器,一是因为Socks5能够非常好的
支持UDP,二是Socks5代理服务器的品种及在公网上部署的数量都比较多,而且最重要的是Socks5是个已标准化了的协议。客户端采用
Socks5代理后,其UDP通信通过Socks5中转出去,在对方的P2P程式看来,使用Socks5代理后的客户就像直接连在公网上,也就是说,只要有一方使用Socks5代理,则另一方不论采用何种NAT,都不会受Stun或natcheck的限制。因此,iptables和Socks5理论上应该合作愉快,但在实现Socks5代理时,如果对Socks5协议理解不够透彻,在和iptables合作时,还是有一些不愉快的。下文试举两例说明之。
假设一端采用iptables,另一端采用Socks5,目前Socks5后面的QQ要向iptables后面的在线(不隐身)QQ发送消息。当QQ通过Socks5代理登陆QQ服务器时,首先要和Socks5服务器建立一个基于TCP连接的Socks5通道,用于控制QQ和Socks5服务器之间的后续UDP联结。一旦该通道成功建立,Socks5服务器将动态分配一个UDP端口为该QQ担任UDP中转的任务,当QQ给远端iptables后面在线QQ发送消息时,先将消息(UDP包)发送到Socks5服务器上先前分配的UDP端口,再由服务器将该UDP包转发到远端QQ。当UDP包到达远端QQ时,
由iptables端口受限的属性可知,除非使用Socks5代理的QQ在线且在不久前(三分钟)原来收到过iptables后面QQ主动发来的UDP包,否则这个包无法被转发到iptables后面的QQ上。
那么这个UDP包最终又往哪里去了呢?我们来分析一下,该UDP包到达iptables所在那台Linux主机后的前进流程。当一个UDP包到达Linux时,先交由iptables处理,iptables则先看该UDP包在/proc/net/ip_conntrack文件里有无匹配项,如有,则进行匹配处理;如无,再看PREROUTING链里有无匹配规则,如有,则继续进行匹配处理;如无,由于该包目的地址就是Linux本身,所以iptables将其放入INPUT链。由于INPUT链的默认策略为ACCEPT,则该UDP包将被转交给Linux的本地进程处理,但事实上由于不存在这样的本地进程,结果是Linux向产生该UDP包的机器发回一个icmp-port-unreachable包(注意,这个包是Linux系统产生的,不是iptables的REJECT目标产生的)。如果INPUT链的策略为DROP,则该UDP包就被DROP。
由上分析可知,一般情况下,最终iptables所在机器将向发送QQ方返回一个icmp-port-unreachable包。当Socks5服务器收到这个icmp-port-unreachable包后,不同的Socks5服务器有不同的处理方式。
一些Socks5服务器(如Ccproxy带的Socks5)简单的忽略这个icmp-port-unreachable包,而QQ则由于没有发送成功
(没有收到应答信息),继续重复上述过程若干次,但都无法发送成功,最后只能通过服务器中转,虽然由于中转造成发送速度非常慢,但总是能够成功发送。而另外
一些Socks5服务器(如Wingate带的Socks5)收到远端返回的icmp-port-unreachable包后,认为先前QQ发起的UDP
联结无效,通过先前建立的Socks5通道(TCP)给客户端返回一个general SOCKS server failure(Reply
Code‘01’),随后即时关闭该通道,同时还关闭了Socks5服务器上担任中转任务的UDP端口。然而QQ似乎并不知道他和Socks5服务器之间
的联系已被切断,由于没有发送成功(没有收到应答信息),仍然向Socks5服务器上已关闭的UDP端口发送消息。此时由于Socks5服务器已关闭了相
应的UDP端口,所以也向QQ返回一个icmp-port-unreachable包。QQ收到这个包后,继续重复上述过程若干次,最终因超时而失败,并
且因为同样的原因也不能通过服务器中转。更为严重的是,即便到了此时,QQ仍然不知道他和Socks5服务器之间的联系已被切断,因此,即使当QQ向其他
离线或隐身QQ或不在NAT后面的在线QQ发送消息时,也不能成功。
上面这个例子表明,由于某些Socks5服务器和Socks5客户端对Socks5协议理解不够透彻,即使采用了Socks5,在和iptables互通时也会导致通讯不畅。
另一个例子,考虑这样一种情形,Socks5服务器位于公网,内网客户端先通过iptables进行NAT,然后再去连接Socks5服务器。
先引用Socks5协议(Rfc1928)里如下一段文字:
The
UDP ASSOCIATE request is used to establish an association within the
UDP relay process to handle UDP datagrams. The DST.ADDR and DST.PORT
fields contain the address and port that the client expects to use to
send UDP datagrams on for the association. The server MAY use this
information to limit access to the association. If the client is not in
possesion of the information at the time of the UDP ASSOCIATE, the
client MUST use a port number and address of all zeros.
Socks5客户端在进行UDPASSOCIATE时(通过TCP通道),需求用自己将来发送UDP包的地址和端口填充DST.ADDR和DST.PORT字段,以便Socks5服务器确保其分配的UDP端口仅为对应的Socks5客户端提供中转服务。然而,当Socks5客户端跨越NAT去连接Socks5服务器时,考虑到要经过
NAT地址转换环节,Socks5客户端无法预知将来Socks5服务器看到的自己用来发送UDP包的地址和端口。针对这种情况,Rfc1928建议
Socks5客户端使用0填充DST.ADDR和DST.PORT字段,这样一来,Socks5服务器就不会限制Socks5客户端对中转端口的使用了。
然而,目前好多Socks5客户端似乎没有意识到这一点,像最通用的NEC公司的e-Border
Driver,便使用了客户端的真实IP地址和端口填充DST.ADDR和DST.PORT字段;而其他一些P2P程式自带的Socks5客户端,仅用0
填充DST.ADDR字段。鉴于跨越NAT后,IP地址必然发生变化,导致e-Border
Driver永远不能用于跨越NAT的场合,而像iptables,由于具有Preserves port
number的属性,所以,那些仅用0填充DST.ADDR字段的Socks5客户端,能用于跨越iptables的场合。此外,跨越NAT还需要
Socks5服务器的配合,遗憾的是,仍然有些Socks5服务器并没有充分理解Rfc1928的这一建议。在这点上,Wingate带的Socks5做
得比较好,支持客户端用0填充DST.ADDR和DST.PORT字段;而Ccproxy带的Socks5,在客户端进行UDP
ASSOCIATE时,虽然也支持客户端用0填充DST.ADDR和DST.PORT字段,并能在服务器上顺利为客户端分配一个UDP端口,但当后来该
UDP端口和客户端通信时,不是发往客户端对应的UDP端口,而是发往客户端前述用0填充的DST.PORT,导致无法实现中转任务。至于NEC公司提供
的广为流传的免费Socks5服务器,则干脆申明“if the destination port is 0, we will assume
the same port as tcp’s”,也将导致Socks5客户端无法跨越NAT。
在这个例子里,iptables对
Socks5代理没有所有影响,纯粹是因为Socks5本身的原因导致通讯不畅。相反,利用iptables的保护源端口特性,还能确保部分Socks5
客户端能够顺利跨越用iptables实现的NAT去连接公网上的Socks5服务器。
希望本文两个例子能对即将或已实现Socks5代理的研发者有所帮助。

iptables下udp穿越实用篇—-iptables与natcheck

文章标题 iptables下udp穿越实用篇—-iptables与natcheck
张贴者: shixudong (member)
张贴日期 10/16/04 05:51 PM

iptables与natcheck

Stun协议(Rfc3489、详见http://www.ietf.org/rfc/rfc3489.txt) 提出了4种NAT类型的定义及其分类,并给出了如何检测在用的NAT究竟属于哪种分类的标准。但是,具体到P2P程序如何应用Stun协议及其分类法穿越NAT,则是仁者见仁、智者见智。(因为Stun协议并没有给出也没有必要给出如何穿越NAT的标准)
在拙作“iptables与stun”一文中,笔者花大幅精力阐述了iptables理论上属于Symmetric NAT而非Port Restricted Cone。对此,很多人(包括笔者最初学习Stun协议时)心中都有一个疑惑,即仅就Stun协议本身来说,Port Restricted Cone和Symmetric NAT的区别似乎不大,虽然两者的映射机制是有点不同,但他们都具有端口受限的属性。初看起来,这两者在穿越NAT方面的特性也差不多,尤其是对于外部地址欲往NAT内部地址发包的情况。既然如此,又为何有必要把iptables分得这么清呢,本文顺带解决了读者在这一方面的疑惑。
网站
http://midcom-p2p.sourceforge.net/给出了P2P程序具体如何穿越NAT的一个思路,并提供了一个P2P协议穿越NAT兼容性的测试工具natcheck。让我们仍旧用实例(例1)来说明这一思路吧!
A机器在私网(192.168.0.4)
A侧NAT服务器(210.21.12.140)
B机器在另一个私网(192.168.0.5)
B侧NAT服务器(210.15.27.140)
C机器在公网(210.15.27.166)作为A和B之间的中介
A机器连接过C机器,假使是 A(192.168.0.4:5000)-> A侧NAT(转换后210.21.12.140:8000)-> C(210.15.27.166:2000)
B机器也连接过C机器,假使是 B(192.168.0.5:5000)-> B侧NAT(转换后210.15.27.140:8000)-> C(210.15.27.166:2000)
A 机器连接过C机器后,A向C报告了自己的内部地址(192.168.0.4:5000),此时C不仅知道了A的外部地址(C通过自己看到的 210.21.12.140:8000)、也知道了A的内部地址。同理C也知道了B的外部地址(210.15.27.140:8000)和内部地址(192.168.0.5:5000)。之后,C作为中介,把A的两个地址告诉了B,同时也把B的两个地址告诉了A。
假设A先知道了B的两个地址,则A从192.168.0.4:5000处同时向B的两个地址192.168.0.5:5000和210.15.27.140:8000发包,由于 A和B在两个不同的NAT后面,故从A(192.168.0.4:5000)到B(192.168.0.5:5000)的包肯定不通,现在看A (192.168.0.4:5000)到B(210.15.27.140:8000)的包,分如下两种情况:
1、B侧NAT属于Full Cone NAT
则无论A侧NAT属于Cone NAT还是Symmetric NAT,包都能顺利到达B。如果P2P程序设计得好,使得B主动到A的包也能借用A主动发起建立的通道的话,则即使A侧NAT属于Symmetric NAT,B发出的包也能顺利到达A。
结论1:只要单侧NAT属于Full Cone NAT,即可实现双向通信。
2、B侧NAT属于Restricted Cone或Port Restricted Cone
则包不能到达B。再细分两种情况
(1)、A侧NAT属于Restricted Cone或Port Restricted Cone
虽然先前那个初始包不曾到达B,但该发包过程已经在A侧NAT上留下了足够的记录:A(192.168.0.4:5000)-> (210.21.12.140:8000)->B(210.15.27.140:8000)。如果在这个记录没有超时之前,B也重复和A一样的动作,即向A(210.21.12.140:8000)发包,虽然A侧NAT属于Restricted Cone或Port Restricted Cone,但先前A侧NAT已经认为A已经向B(210.15.27.140:8000)发过包,故B向A(210.21.12.140:8000)发包能够顺利到达A。同理,此后A到B的包,也能顺利到达。
结论2:只要两侧NAT都不属于Symmetric NAT,也可双向通信。换种说法,只要两侧NAT都属于Cone NAT,即可双向通信。
(2)、A侧NAT属于Symmetric NAT
因为A侧NAT属于Symmetric NAT,且最初A到C发包的过程在A侧NAT留下了如下记录:A(192.168.0.4:5000)->(210.21.12.140: 8000)-> C(210.15.27.166:2000),故A到B发包过程在A侧NAT上留下的记录为:A(192.168.0.4:5000)-> (210.21.12.140:8001)->B(210.15.27.140:8000)(注意,转换后端口产生了变化)。而B向A的发包,只能根据C给他的关于A的信息,发往A(210.21.12.140:8000),因为A端口受限,故此路不通。再来看B侧NAT,由于B也向A发过了包,且 B侧NAT属于Restricted Cone或Port Restricted Cone,故在B侧NAT上留下的记录为:B(192.168.0.5:5000)->(210.15.27.140:8000)->A (210.21.12.140:8000),此后,如果A还继续向B发包的话(因为同一目标,故仍然使用前面的映射),如果B侧NAT属于 Restricted Cone,则从A(210.21.12.140:8001)来的包能够顺利到达B;如果B侧NAT属于Port Restricted Cone,则包永远无法到达B。
结论3:一侧NAT属于Symmetric NAT,另一侧NAT属于Restricted Cone,也可双向通信。
显然,还可得出另一个不幸的结论4,两个都是Symmetric NAT或者一个是Symmetric NAT、另一个是Port Restricted Cone,则不能双向通信。
上面的例子虽然只是分析了最初发包是从A到B的情况,但是,鉴于两者的对称性,并且如果P2P程序设计得足够科学,则前面得出的几条结论都是没有方向性,双向都适用的。
通过上述分析,我们得知,在穿越NAT方面,Symmetric NAT和Port Restricted Cone是有本质区别的,尽管他们表面上看起来相似。我们上面得出了四条结论,而natcheck网站则把他归结为一条:只要两侧NAT都属于Cone NAT(含Full Cone、Restricted Cone和Port Restricted Cone三者),即可双向通信。而且natcheck网站还建议尽量使用Port Restricted Cone,以充分利用其端口受限的属性确保安全性。目前,国内充分利用了上述思路的具有代表性的P2P软件是“E话通”(
www.et66.com)。
在对natcheck提供的思路进行详细分析后,开始探讨本文主题:iptables与natcheck。
Natcheck 脱胎于Stun协议,由拙作“iptables与stun”一文可知,其对iptables进行的穿越NAT兼容性测试结果必然是GOOD。此外,我在该文中还提到一句,如果在每个NAT后面仅有一个客户端这种特殊情况下,iptables就是一个标准的Port restricted Cone。根据前面natcheck的结论,这样两个iptables后面的客户端应该可以互相穿越对方的NAT。让我们来看一下实际情况(例2)呢?
仍然参考前例,只是两侧都使用iptables来进行地址转换。(因为采用了iptables,故此处和前例稍有点区别,即转换后源端口不变)
A 与B通过C交换对方地址的初始化环节此处略去,我们从A(192.168.0.4:5000)向B(210.15.27.140:5000)(注意因使用 iptables而导致端口和前例不一样)发包开始分析,因为在本例中,两侧均只有一个客户端,我们姑且把iptables简化成Port restricted Cone看待。
如前例一样,从A(192.168.0.4:5000)到B(210.15.27.140: 5000)的第一个包必不能到达B,但其会在A侧iptables上留下记录,在这条记录没有超时之前(iptables下默认30秒),如果B也向A (210.21.12.140:5000)发包,如前所述,按理该包应该能够到达A,但事实上却是永远到不了。
难道是natcheck的结论错了,或者是特殊情况下iptables并不是Port restricted Cone(即仍然是Symmetric NAT),我们还是别忙着再下结论,先来看看来两侧iptables上留下的记录吧:
A侧:cat /proc/net/ip_conntrack | grep 192.168.0.4 | grep udp
udp 17 18 src=192.168.0.4 dst=210.15.27.140 sport=5000 dport=5000 [UNREPLIED] src=210.15.27.140 dst=210.21.12.140 sport=5000 dport=5000 use=1
B侧:cat /proc/net/ip_conntrack | grep 192.168.0.5 | grep udp
udp 17 26 src=192.168.0.5 dst=210.21.12.140 sport=5000 dport=5000 [UNREPLIED] src=210.21.12.140 dst=210.15.27.140 sport=5000 dport=1026 use=1
把两条记录翻译如下:(关于ip_conntrack文件的分析,请见
http://www.sns.ias.edu/~jns/secu … bles_conntrack.html
A(192.168.0.4:5000)-> A侧NAT(转换后210.21.12.140:5000)-> B(210.15.27.140:5000)
B(192.168.0.5:5000)-> B侧NAT(转换后210.15.27.140:1026)-> A(210.21.12.140:5000)
奇怪,B到A的包在映射后源端口号怎么变了呢,按理不应该呀?因为按照iptables转换原则(详见“iptables与stun”),要求尽量保持源端口号不变,除非socket有重复。难道B侧NAT上还有重复记录,再cat一下呢?
B侧:cat /proc/net/ip_conntrack | grep 210.21.12.140 | grep udp
udp 17 10 src=210.21.12.140 dst=210.15.27.140 sport=5000 dport=5000 [UNREPLIED] src=210.15.27.140 dst=210.21.12.140 sport=5000 dport=5000 use=1
udp 17 16 src=192.168.0.5 dst=210.21.12.140 sport=5000 dport=5000 [UNREPLIED] src=210.21.12.140 dst=210.15.27.140 sport=5000 dport=1026 use=1
操!还果真有两条差不多的记录,第一条与NAT无关,是A到B的包在B侧iptables上留下的记录,产生时间上略早于第二条记录,其构成的socket是(210.21.12.140:5000,210.15.27.140:5000)。第二条即B到A的包产生的记录,其构成的socket是(210.15.27.140:1026,210.21.12.140:5000),如果其源端口不改动,即是(210.15.27.140:5000,210.21.12.140:5000),还真和第一条记录重复了呢,怪不得转换后需要修改源端口,也怪不得B 发包到不了A。
为什么是这样的结果呢?我们知道,iptables是一个有状态的防火墙,他通过连接跟踪模块来实现状态检测的功能,该模块检查所有到来的数据包,也就是说,该模块不仅对NAT起作用,而且对普通的包过滤也起作用。显然,在上述例子里,A到B的包就是作为普通的包过滤而被记载在 B侧iptables的连接跟踪表里,导致后来B到A的包为避免socket重复而不得不改换端口号,从而导致无法实现双向通信。看来,natcheck 的结论并没有错,只是由于iptables具有状态检测的新特性导致即使在特殊情况下iptables又从Port restricted Cone变成了Symmetric NAT而已。
那么,有办法解决这一问题吗?根据连接跟踪的特性,在iptables下,只要启用了 NAT,就肯定要启用连接跟踪功能,而只要启用了连接跟踪功能,就必然顺带跟踪普通包过滤(启用连接跟踪后,似乎无法控制不让跟踪普通包过滤),也就是说,只要用NAT,就无法避免上述情况,真残酷!然而,这却是事实,即只要两端都采用了iptables作为NAT,则尽管两侧都通过了natcheck 的兼容性测试,但iptables两侧永远也不能互相穿越。
在“iptables与stun”一文中曾经附带提到,Win2000下的ics 或nat在Stun协议下的表现和iptables是完全一样的。那么,在natcheck下,表现是否还一致呢?答案是否定的,虽然Win2000下的 ics或nat也具有状态检测的功能,但该状态检测,仅对NAT起作用,不对普通包过滤起作用。所以在两侧都是Win2000下的ics或nat可以作为 Port restricted Cone的特殊情况下,是允许被穿越的。另外,在一侧使用iptables,另一侧使用Win2000下的ics或nat,但两者都表现为Port restricted Cone的特殊情况下,从某个方向发起,最终是允许互相穿越的,但是这种穿越不具有对称性,即从另一个方向发起,则永远无法穿越,具体原理,读者可以参考例2自行分析。