Php session内部执行流程的再次剖析

没有评论

2013 年 03 月 25 日 at 下午 2:48分类:PHP

近期再次分析了php session内部的执行流程,我将在这篇文章中简要地概括出php内部关于session的执行步骤。
首先php中的session其实就是作为一个扩展载入到php内核中的。我们可以将它理解成一个扩展就可以了。当session扩展被载入时,php会调用内部核心函数来获取处理session的save_handler – 也就是存储读取session数据的接口类或者函数。 Php默认地是通过写或者读取文件来处理session数据的。但是,php也提供了user自定义的方式 – 也就是自定义处理session数据的接口,可以通过session_set_save_handler函数来注册。关于这方面,后续我会详细写一篇文章。同时,php会判断session.auto_start是否已经在配置中默认开启。如果开启了session.auto_start,PHP便会调用内部函数自动开启Session功能。以上,就是session扩展被载入时php内部所处理的两件事情。
接下来,php在启动session的时候,如果发现请求的Cookies,Get,Post中不存在session id,说明这是客户端的第一次访问,php会自动调用php_session_create_id函数创建一个唯一的session id,并且在http response中通过set-cookie头部发送给客户端保存(在客户端cookie被禁用的情况下,php也可以自动将session id添加到url参数中以及form的hidden 字段中,这需要将php.ini中的session.use_trans_sid设为开启,也可以在运行时调用ini_set来设置这个配置项)。相反,如果请求中已经携带了session id,那么php会做以下几件事情:
1、从cookie中获取Session ID
2、调用save_handler的open接口打开存储上下文
3、如果读取不到对应的session id, 生成新的Session Id
4、注册$_SESSION和$_HTTP_SESSION_VARS全局变量,$_SESSION和$_HTTP_SESSION_VARS会被注册为同一个数组
5、接着调用save_handler的read接口读取Session数据,如果是使用files方式存储的话,就从文件中读取Session数据,数据库方式的话,就从数据库中读取。 读取完毕后会把读到的数据写入到$_SESSION数组中
最后,当一个请求执行完毕时,php会调用内部函数获取$_SESSION数组中的值,然后调用php_session_encode将其系列化后,通过调用save_handler的write接口将session系列化数据存储起来。
以上大致按照顺序列出了php session的内部执行流程。

转载自:http://www.360weboy.com/php/session-cookie/php_session.html

同一域名对应多个IP时,PHP获取远程网页内容的函数[转载]

没有评论

2013 年 03 月 12 日 at 下午 9:03分类:PHP

PHP获取远程网页内容有多种方式,例如用自带的file_get_contents、fopen等函数。

<?php   
echo file_get_contents("http://www.fbbin.com/test.php");   
?>

但是,在DNS轮询等负载均衡中,同一域名,可能对应多台服务器,多个IP。假设www.fbbin.com被DNS解析到173.231.44.230、173.231.44.231、173.231.44.232三个IP,用户每次访问www.fbbin.com,系统会根据负载均衡的相应算法访问其中的一台服务器。
上周做一个视频项目时,就碰到这样一类需求:需要依次访问每台服务器上的一个PHP接口程序(假设为abc.php),查询这台服务器的传输状态。
这时就不能直接用file_get_contents访问http://www.fbbin.com/test.php了,因为它可能一直重复访问某一台服务器。
而采用依次访问http://173.231.44.230/test.php、http://173.231.44.231/test.php、http://173.231.44.232/test.php的方法,在这三台服务器上的Web Server配有多个虚拟主机时,也是不行的。通过设置本地hosts也不行,因为hosts不能设置多个IP对应同一个域名。
那就只有通过PHP和HTTP协议来实现:访问test.php时,在header头中加上www.fbbin.com域名。思路是这样子的:
如果那三台服务器有对外的IP,则做个host指向过去就可以定向抓取了~
程序实现的话,我觉得应该是这样的思路:
1) 用fsockopen建立与指定IP的80端口的连接;
2) 构造http头信息
GET status.html HTTP/1.1
Host: www.fbbin.com
发送到目标服务器
3) 获取服务器端返回的内容
4) 多IP轮询一遍就行了。
下面用PHP函数予以实现。

<?php
/************************
* 函数用途:同一域名对应多个IP时,获取指定服务器的远程网页内容
* 创建时间:2008-12-09
* 创建人:张宴(blog.s135.com)
* 参数说明:
*    $ip   服务器的IP地址
*    $host   服务器的host名称
*    $url   服务器的URL地址(不含域名)
* 返回值:
*    获取到的远程网页内容
*    false   访问远程网页失败
************************/
function HttpVisit($ip, $host, $url)   
{   
    $errstr = '';   
    $errno = '';
    $fp = fsockopen ($ip, 80, $errno, $errstr, 90);
    if (!$fp)   
    {   
         return false;   
    }   
    else  
    {   
        $out = "GET {$url} HTTP/1.1\r\n";
        $out .= "Host:{$host}\r\n";   
        $out .= "Connection: close\r\n\r\n";
        fputs ($fp, $out);   

        while($line = fread($fp, 4096)){
           $response .= $line;
        }
        fclose( $fp );

        //去掉Header头信息
        $pos = strpos($response, "\r\n\r\n");
        $response = substr($response, $pos + 4);
    
        return $response;   
    }   
}

//调用方法:
$server_info1 = HttpVisit("173.231.44.230", "www.fbbin.com", "/test.php");
$server_info2 = HttpVisit("173.231.44.231", "www.fbbin.com", "/test.php");
$server_info3 = HttpVisit("173.231.44.232", "www.fbbin.com", "/test.php");
?>