关于Cache-control的一些认识

网页的缓存是由HTTP消息头中的“Cache-control”来控制的,常见的取值有private、no-cache、max-age、must-revalidate等,默认为private。其作用根据不同的重新浏览方式分为以下几种情况:
(1) 打开新窗口
如果指定cache-control的值为private、no-cache、must-revalidate,那么打开新窗口访问时都会重新访问服务器。而如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器,例如:
Cache-control: max-age=5
表示当访问此网页后的5秒内再次访问不会去服务器
(2) 在地址栏回车
如果值为private或must-revalidate(和网上说的不一样),则只有第一次访问时会访问服务器,以后就不再访问。如果值为no-cache,那么每次都会访问。如果值为max-age,则在过期之前不会重复访问。
(3) 按后退按扭
如果值为private、must-revalidate、max-age,则不会重访问,而如果为no-cache,则每次都重复访问
(4) 按刷新按扭
无论为何值,都会重复访问

当指定Cache-control值为“no-cache”时,访问此页面不会在Internet临时文章夹留下页面备份。
另外,通过指定“Expires”值也会影响到缓存。例如,指定Expires值为一个早已过去的时间,那么访问此网时若重复在地址栏按回车,那么每次都会重复访问:
Expires: Fri, 31 Dec 1999 16:00:00 GMT

在ASP中,可以通过Response对象的Expires、ExpiresAbsolute属性控制Expires值;通过Response对象的CacheControl属性控制Cache-control的值,例如:
Response.ExpiresAbsolute = #2000-1-1# ‘ 指定绝对的过期时间,这个时间用的是服务器当地时间,会被自动转换为GMT时间
Response.Expires = 20 ‘ 指定相对的过期时间,以分钟为单位,表示从当前时间起过多少分钟过期。
Response.CacheControl = "no-cache"

详细确切的定义建议参考rfc :http://www.w3.org/Protocols/rfc2616/rfc2616.html

VIM设置代码折叠

1. 折叠方式
可用选项 ‘foldmethod’ 来设定折叠方式:set fdm=*****
有 6 种方法来选定折叠:
          manual           手工定义折叠
          indent             更多的缩进表示更高级别的折叠
          expr                用表达式来定义折叠
          syntax             用语法高亮来定义折叠
          diff                  对没有更改的文本进行折叠
          marker            对文中的标志折叠

注意,每一种折叠方式不兼容,如不能即用expr又用marker方式,我主要轮流使用indent和marker方式进行折叠。

使用时,用:set fdm=marker 命令来设置成marker折叠方式(fdm是foldmethod的缩写)。
要使每次打开vim时折叠都生效,则在.vimrc文件中添加设置,如添加:set fdm=syntax,就像添加其它的初始化设置一样。

2. 折叠命令
选取了折叠方式后,我们就可以对某些代码实施我们需要的折叠了,由于我使用indent和marker稍微多一些,故以它们的使用为例:
如果使用了indent方式,vim会自动的对大括号的中间部分进行折叠,我们可以直接使用这些现成的折叠成果。
在可折叠处(大括号中间):
zc      折叠
zC     对所在范围内所有嵌套的折叠点进行折叠
zo      展开折叠
zO     对所在范围内所有嵌套的折叠点展开
[z       到当前打开的折叠的开始处。
]z       到当前打开的折叠的末尾处。
zj       向下移动。到达下一个折叠的开始处。关闭的折叠也被计入。
zk      向上移动到前一折叠的结束处。关闭的折叠也被计入。

当使用marker方式时,需要用标计来标识代码的折叠,系统默认是{{{和}}},最好不要改动之:)
我们可以使用下面的命令来创建和删除折叠:
zf      创建折叠,比如在marker方式下:
                   zf56G,创建从当前行起到56行的代码折叠;
                   10zf或10zf+或zf10↓,创建从当前行起到后10行的代码折叠。
                   10zf-或zf10↑,创建从当前行起到之前10行的代码折叠。
                   在括号处zf%,创建从当前行起到对应的匹配的括号上去((),{},[],<>等)。
zd      删除 (delete) 在光标下的折叠。仅当 ‘foldmethod’ 设为 "manual" 或 "marker" 时有效。
zD     循环删除 (Delete) 光标下的折叠,即嵌套删除折叠。
          仅当 ‘foldmethod’ 设为 "manual" 或 "marker" 时有效。
zE     除去 (Eliminate) 窗口里“所有”的折叠。
          仅当 ‘foldmethod’ 设为 "manual" 或 "marker" 时有效。

关于vim的代码折叠,小弟也是初学,仅做参考。

file_get_contents 与 http1.1

曾经测试过file_get_contents函数的post实现,现在又想知道file_get_contents 能否实现http的长连接,测试代码:

<?php
$url 
"http://phpor.net/"
;
$opts 
= array(
  
‘http’
=>array(
      
‘protocol_version’=>"1.1"
,
      )
  );

$context stream_context_create($opts);
echo 
strlenfile_get_contents($url,false,$context))."\n"
;
echo 
strlenfile_get_contents($url,false,$context))."\n"
;
?>

该脚本将产生异常,在Linux上执行将是段错误。

下面脚本可以正常输出:

<?php
$url 
"http://phpor.net/";
$opts = array(
  
‘http’=>array(
      
‘protocol_version’=>"1.1",
      
‘connection’=>‘close’
      
)
  );

$context stream_context_create($opts);
echo 
file_get_contents($url,false,$context)."\n";
?>

但是这时我们将发现输出的东西比网页的内容多一些,那是trunked编码,这说明file_get_contents更本就不识别chunked编码,所以file_get_contents 根本就没法实现长连接。

当然可以用curl实现:

<?php
$url 
"http://phpor.net/"
;
$ch curl_init
();
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1
);
curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_0
);
curl_setopt($chCURLOPT_URL$request
);                                                      
$res curl_exec($ch
);
echo 
$res
;
curl_close($ch
);

?>

javascript的script标签的用法

请看下面两段代码有什么区别:

1.==============a1.html==========================

<script >
window.location.href="http://phpor.net
";
alert(‘aa’
);
</script>

2.=============a2.html===========================

<script >
window.location.href="http://phpor.net
";
</script>

<script >
alert(‘aa’
);
</script>

访问a1.html  ,看不到alert
访问a2.html  ,能看到alert

这就可以说明一些script标签的作用

date 命令的简单用法

1. 显示当前的时间戳

date +%s

2. 修改系统时间

date  -s 2008-08-08 08:08:08

3. 转化时间字符串为时间戳

date +%s  -d "2008-08-08 08:08:08"

注意: 不要无意将 -d 写成-s ,那样你就无意修改了系统时间了

4. 按照指定格式输出时间

date +%F           // 输出: 2009-09-22

date +%F –date=’1 days ago’          // 输出: 2009-09-21

连接时间的计算

对于一些非长连接的应用,可以通过计算连接的持续时间来知道处理时间的长短,首先通过tcpdump抓包,通过tcptrace可以知道连接的开始和结束时间,再用awk就可以统计了,基本命令如下:

tcpdump -i eth1 -w -| tcptrace -xrealtime stdin | awk ‘{ link = $2 "-" $3;if($4=="new")sum[link] = $1; else if($4 =="connection" && sum[link] > 0){ print link "\t" ($1-sum[link]) "\t" $6 " " $7 " " $8; delete sum[link];}}’

好像tcptrace本身是可以计算连接时间的长短的,应该是我还没有发现。

找见了:

tcptrace -l a.tcpdump | grep "elapsed time"

 

tcp 协议里的时间

一、建立连接

在发送SYN报文段后,如果在75没有收到相应相应,连接建立将中止。这个时间也就是阻塞connect系统调用的超时时间。

 

二、保活

SO_KEEPALIVE选项保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:对方接收一切正常:以期望的ACK响应。2小时后,TCP将发出另一个探测分节。对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接口本身则被关闭。对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟 15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。

注意这里面有三个数字:

1.开始首次KeepAlive探测前的TCP空闭时间,2小时

2.两次KeepAlive探测间的时间间隔,75

3.判定断开前的KeepAlive探测次数,10

也就是说,总共需要2小时+75秒*10次 = 7950

 

三、重传

重传定时器在发送数据时设定,超时值是计算出来的,取决于RTT和报文已被重传次数(并没有包括在以下公式内,但是BSD的实现确实用到了这个数据)。

RTT估计其,R是RTT,M是测量到的RTT,a推荐值为0.9

R = a * R + (1-a) * M

重传超时时间RTO, b推荐值为2

RTO = R * b

例外:快速重传,收到3个重复的ACK会立即重传

 

四、延时确认,捎带确认

TCP协议栈收到数据后并不立即发送ACK,而是等待200ms(推荐值,但是这个值不能高于500ms),如果在这段时间有用户数据需要发送则一同随着这个ACK发送。

 

五、FIN_WAIT_2定时器

某个连接准备关闭连接时,调用close函数,发送FIN报文,状态从SYN_RCVD迁移到FIN_WAIT_1,收到这个FIN的ACK后,迁移到FIN_WAIT_2状态。

为了防止对端一直不发送FIN,在等待10分钟后再等待75(定时器确实被设置了两次,所以分开说),超时,连接关闭。

 

六、2MSL定时器

MSL是最大报文段生存时间,RFC1122建议是2分钟,但BSD传统实现采用了30。当连接转移到TIME_WAIT状态时,即连接主动关闭时,定时器启动,为两倍的MSL。定时器超时,这时才能重新使用之前连接使用的端口号。这也是为了避免一些意想不到的边界情况,TCPIP详解第一卷的18.6.1给出了一个极端的例子。

 

七、平静时间

对于来自某个连接的较早替身的迟到报文段, 2 M S L等待可防止将它解释成使用相同插口对的新连接的一部分。但这只有在处于2 M S L等待连接中的主机处于正常工作状态时才有效。

如果使用处于2 M S L等待端口的主机出现故障,它会在M S L秒内重新启动,并立即使用故障前仍处于2 M S L的插口对来建立一个新的连接吗?如果是这样,在故障前从这个连接发出而迟到的报文段会被错误地当作属于重启后新连接的报文段。无论如何选择重启后新连接的初始序号,都会发生这种情况。

为了防止这种情况,RFC 793指出TCP在重启动后的MSL内不能建立任何连接。这就称为平静时间(quiet time)

 

八、SO_LINGER的时间

这个选项会影响close的行为。如果linger结构中的l_onoff域设为非零,并设置了零超时间隔,则close不被阻塞立即执行,不论是否有排队数据未发送或未被确认。这种关闭方式会发送RST报文段,且丢失了未发送的数据。在远端的读调用将以ECONNRESET出错。

若设置了SO_LINGER并确定了非零的超时间隔,则closes调用阻塞进程,直到所剩数据发送完毕或超时。这种关闭称为“优雅的”关闭。如果套接口置为非阻塞且SO_LINGER设为非零超时,则close调用将以EWOULDBLOCK错误返回。

若在一个流类套接口上设置了SO_DONTLINGER(等效于SO_LINGER将linger结构的l_onoff域设为零),则close调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。

web 上获取用户ip的函数

下面是一个常见的获取用户ip的函数:

<?php
function getip
()
{
    if(
getenv("HTTP_CLIENT_IP") && getenv("HTTP_CLIENT_IP")!="unknown"
)
        
$ip getenv("HTTP_CLIENT_IP"
);
    elseif(
getenv("HTTP_X_FORWARDED_FOR") && getenv("HTTP_X_FORWARDED_FOR")!="unknown"
)
        
$ip getenv("HTTP_X_FORWARDED_FOR"
);
    elseif(
getenv("REMOTE_ADDR") && getenv("REMOTE_ADDR")!="unknown"
)
        
$ip getenv("REMOTE_ADDR"
);
    else    
        
$ip "none"

    return $ip;
}
?>

下面给出一个测试脚本:

<?php
$ch 
curl_init();
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);
curl_setopt($ch,CURLOPT_HTTPHEADER,array(‘X_FORWARDED_FOR: 158.10.10.10’));
curl_setopt($ch,CURLOPT_HTTPHEADER,array(‘CLIENT_IP: 159.10.10.10’));
curl_setopt($chCURLOPT_URL,"http://10.10.10.21/test.php");
echo 
curl_exec($ch);
curl_close($ch);
exit;
?>