首頁 >後端開發 >php教程 >PHP fsockopen函數詳解

PHP fsockopen函數詳解

尚
轉載
2020-03-17 09:49:387298瀏覽

PHP fsockopen函數詳解

PHP fsockopen是一個比較強大的函數。我們在這篇文章中將會對這個函數做一個具體的介紹,希望對大家有幫助。記得以前的B2C網站就是透過這個函數實現前台和訂單處理系統的互動。

PHP fsockopen函數說明:

語法:

resource fsockopen ( string $hostname [, int KaTeX parse error: Expected 'EOF', got '&' at position 20 : … = -1 [, int &̲errno [, string &$errstr [, float $timeout = ini_get(“default_socket_timeout”) ]]]] )

開啟PHP fsockopen這個函數

PHP fsockopen需要PHP.ini 中allow_url_fopen 選項開啟。

allow_url_fopen = On

參數:

hostname:如果安裝了OpenSSL,那麼你也許應該在你的主機名稱位址前面加上存取協定ssl://或是tls://,從而可以使用基於TCP/IP協定的SSL或TLS的客戶端連接到遠端主機。

port:連接埠號碼。如果對該參數傳遞一個-1,則表示不使用端口,例如unix://。

errno:如果errno的回傳值為0,而且這個函數的回傳值為FALSE ,那麼這表示該錯誤發生在套接字連線(connect())呼叫之前,導致連線失敗的原因最大的可能是初始化套接字的時候發生了錯誤。

errstr:錯誤訊息將以字串的訊息傳回。

timeout:設定連線的時限,單位為秒。

傳回值:

fsockopen() 會傳回一個檔案句柄,之後可以被其他檔案類別函數呼叫(例如: fgets() , fgetss() , fwrite() , fclose()還有feof() )。如果呼叫失敗,將傳回 FALSE 。

php fsockopen使用案例

1、fsockopen 來模擬產生HTTP 連線

<?php
    $fp = fsockopen("127.0.0.1",80,$errno,$errstr,30);
    if(!$fp){
        echo "$errstr ($errno)<br />\n";
    }else{
        $out = "GET / HTTP/1.1\r\n";
        $out .= "Host: 127.0.0.1\r\n";
        $out .= "Connection: Close\r\n\r\n";
        fwrite($fp,$out);
        $content = &#39;&#39;;
        while(!feof($fp)){
            $content .= fgets($fp,128);
        }
        echo $content;
        fclose($fp);
    }
?>

執行結果:

PHP fsockopen函數詳解

#2、PHP fsockopen模擬POST/GET方法

fsockopen除了像上面實例模擬產生HTTP 連線之外,還能實現許多功能,例如模擬post 和get 傳送資料的方法。
get :

<?php
$url = "http://localhost/test2.php?site=www.tbrer.com";
print_r(parse_url($url));// 解析 URL,返回其组成部分

/* get提交 */
sock_get($url,&#39;user=gonn&#39;);

// fsocket模拟get提交
function sock_get($url,$query){
    $data = array(
        &#39;foo&#39; => &#39;bar&#39;,
        &#39;baz&#39; => &#39;boom&#39;,
        &#39;site&#39; => &#39;www.tbrer.com&#39;,
        &#39;name&#39; => &#39;nowa magic&#39;
    );

    $query_str = http_build_query($data);// http_build_query()函数的作用是使用给出的关联(或下标)数组生成一个经过 URL-encode 的请求字符串

    $info = parse_url($url);
    $fp = fsockopen($info["host"],80,$errno,$errstr,30);
    $head = "GET " . $info[&#39;path&#39;] . &#39;?&#39; . $query_str . " HTTP/1.0\r\n";
    $head .= "Host: " . $info[&#39;host&#39;] . "\r\n";
    $head .= "\r\n";
    $write = fputs($fp,$head);
    while(!feof($fp)){
        $line = fread($fp,4096);
        echo $line;
    }
}
?>

post :

<?php
$url = "http://localhost/test2.php?site=www.tbrer.com";
print_r(parse_url($url));// 解析 URL,返回其组成部分

/* get提交 */
sock_post($url,&#39;user=gonn&#39;);

// fsocket模拟get提交
function sock_post($url,$query){
    $info = parse_url($url);
    $fp = fsockopen($info["host"],80,$errno,$errstr,30);
    $head = "POST " . $info[&#39;path&#39;] . "?" . $info["query"] . " HTTP/1.0\r\n";
    $head .= "Host: " . $info[&#39;host&#39;] . "\r\n";
    $head .= "Referer: http://" . $info[&#39;host&#39;] . $info[&#39;path&#39;] . "\r\n";
    $head .= "Content-type: application/x-www-form-urlencoded\r\n";
    $head .= "Content-Length: ". strlen(trim($query)) . "\r\n";
    $head .= "\r\n";
    $head  .= trim($query);
    $write = fputs($fp,$head);
    while(!feof($fp)){
        $line = fread($fp,4096);
        echo $line;
    }
}
?>

接收頁面test2.php 的程式碼為:

<?php
    $data = $_REQUEST;

    echo &#39;<pre class="brush:php;toolbar:false">&#39;;
    print_r($data);
    echo &#39;
'; ?>

3、fsockopen以Socket方式模擬HTTP下載檔案

<?php
    /* 
        *   Socket 模拟HTTP协议传输文件
        *   Http是应用层协议使用80端口
    */
    $hostname = &#39;127.0.0.1&#39;;
    $port = &#39;80&#39;;

    // 建立连接
    $fp = fsockopen($hostname,$port,$errno,$errstr);
    stream_set_blocking($fp,true);
    if(!$fp){
        echo "$errno : $errstr<br />";
    }else{
        // 发送一个HTTP请求信息头
        $request_header = "GET /aaa.txt";

        // 起始行
        // 头域 
        $request_header .= "Host: $hostname\n";
        
        // 再一个回车换行表示头信息结束
        $request_header .= "\n";

        // 发送请求到服务器
        fputs($fp,$request_header);

        // 接受响应
        $fp2 = fopen(&#39;aaa.txt&#39;,&#39;w&#39;);

        while(!feof($fp)){
            $line = fputs($fp2,fgets($fp,128));
            echo $line;
        }

        // 关闭
        fclose($fp2);
        fclose($fp);
    }
?>

執行程序,你會發現在這個程式檔案的同級目錄就會出現那個你需要下載的檔案了。

這實質上是 Socket 模擬HTTP協定傳輸檔案。同時也要注意 PHP 的逾時限制,這裡設定我 PHP 伺服器逾時為無限才能正確下載,否則可能下載不完全 PHP 程式就停止了。

注意:

bool stream_set_blocking ( resource $stream , int $mode )

為 stream 設定阻塞或是阻塞模。

此函數適用於支援非阻塞模式的任何資源流(常規文件,套接字資源流等)。

參數

stream:資源流。

mode:如果 mode 為0,資源流將會轉換為非阻塞模式;如果是1,資源流將會轉換為阻塞模式。該參數的設定將會影響到像 fgets() 和 fread() 這樣的函數從資源流讀取資料。在非阻塞模式下,呼叫 fgets() 總是會立即回傳;而在阻塞模式下,將會一直等到從資源流裡面取得到資料才能回傳。

傳回值

成功時傳回 TRUE, 或在失敗時回傳 FALSE。

4、使用fsockopen 偽造來路

<?php
$host = "127.0.0.1"; //你要访问的域名
$ip = &#39;127.0.0.1&#39;;
$target = "/test2.php"; //你要访问的页面地址
$referer = "http://www.tbrer.com/"; //伪造来路页面
//$fp = fsockopen($host, 80, $errno, $errstr, 30);
$fp = fsockopen($ip, 80, $errno, $errstr, 30);
if(!$fp)
{
    echo "$errstr($errno)<br />\n";
}
else
{
	$end = "\r\n";
    $out = "GET $target HTTP/1.1$end";
	$out .= "Host: $ip$end";
	$out .= "Referer: $referer$end";
	$out .= "Connection: Close$end";
	$out .= "$end";
    fwrite($fp, $out);
    while(!feof($fp))
    {
        echo fgets($fp, 1024);
    }
    fclose($fp);
}
?>

test2.php 的程式碼為:

<?php
    $data = $_REQUEST;

    echo &#39;<pre class="brush:php;toolbar:false">&#39;;
    print_r($data);
    echo &#39;
'; ?>

可以看到HTTP_REFERER 的值為 http://www.tribrer.com /,即來路已經偽造成功。

相關推薦:

PHP影片教學:https://www.php.cn/course/list/29/type/2.html

以上是PHP fsockopen函數詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除