PHP Socket編程 之 fsockopen異步請求執行https(ssl)站點方法分享


1、 fsockopen

/**
 * 異步 執行程序
 * @param string $path 異步url 地址
 * @param array $postData 傳遞的參數
 * @param string $method 請求方式
 * @param string $url 請求地址
 * @return bool
 */
function request_asynchronous($path, $method = "POST", $postData = array(), $url = ''){
    if(empty($path)){
        return false;
    }
 
    if($url) {
        $matches = parse_url($url);
        $host = $matches['host'];
        //$path = $matches['path'] ? $matches['path'] . ($matches['query'] ? '?' . $matches['query'] : '') : '/';
        if ($matches['scheme'] == 'https') { //判斷是否使用HTTPS
            $transports = 'ssl://';  //如使用HTTPS則使用SSL協議
            $port = !empty($matches['port']) ? $matches['port'] : 443; //如使用HTTPS端口使用443
        } else {
            $transports = 'tcp://'; //如沒有使用HTTPS則使用tcp協議
            $port = !empty($matches['port']) ? $matches['port'] : 80;//如沒有使用HTTPS則使用80端口
        }
    }else{
        $port = 443;
        $transports = 'ssl://';
        $host = $_SERVER['HTTP_HOST'];
    }
 
    $errNo = 0;
    $errStr = '';
    $timeout = 60;
    $fp = '';
    if(function_exists('fsockopen')) {
        $fp = @fsockopen(($transports . $host), $port, $errno, $errStr, $timeout);
    } elseif(function_exists('pfsockopen')) {
        $fp = @pfsockopen($transports.$host, $port, $errNo, $errStr, $timeout);
    } elseif(function_exists('stream_socket_client')) {
        $fp = @stream_socket_client($transports.$host.':'.$port, $errNo, $errStr, $timeout);
    }
 
    if (!$fp) {
        return false;
    }
 
    stream_set_blocking($fp, 0); //開啟非阻塞模式
    stream_set_timeout($fp,  3); //設置超時時間(s)
 
    $date = [];
    if($postData) {
        //處理文件
        foreach ($postData as $key => $value) {
            if(is_array($value)){
                $date[$key] = serialize($value);
            }else{
                $date[$key] = $value;
            }
        }
    }
 
    if ($method == "GET") {
        $query = $date ? http_build_query($date) : '';
        $path .= "?".$query;
    }else{
        $query = json_encode($date);
    }
 
    $cookie = "token={$_COOKIE['token']}; session={$_COOKIE['session']}";
    //http消息頭
    $out = $method." ".$path." HTTP/1.1\r\n";
    $out .= "HOST: ".$host."\r\n";
    if ($method == "POST") {
        $out .= "Content-Length:".strlen($query)."\r\n";
    }
    $out .= "Accept: application/json, text/plain, */*\r\n";
    $out .= "Access-Control-Allow-Credentials: true\r\n";
    $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out .= "Cookie: ".$cookie."\r\n";
    $out .= "Connection: Close\r\n\r\n";
    if ($method == "POST") {
        $out .= $query;
    }
 
    fputs($fp, $out);
    usleep(500);
    //忽略執行結果
    /*while (!feof($fp)) {
        echo fgets($fp, 128);
    }*/
    fclose($fp);
 
    return true;
}

2、CURL

/**
 * 發送https/http請求  正常/異步
 * @param string $url 請求地址
 * @param array $params http請求數據, 數據類型必須是Array
 * @param string $method http方法(GET POST PUT DELETE)
 * @param array $header http請求頭
 * @param int $type 請求類型 0正常,1異步
 * @return string|bool
 */
function request_curl($url, $params = [], $method = "POST", $header = [], $type = 0) {
    //檢查地址是否為空
    if (empty($url)) {
        return false;
    }
    //控制請求方法范圍
    $httpMethod = array('GET', 'POST', 'PUT', 'DELETE');
    $method = strtoupper($method);
    if (!in_array($method, $httpMethod)) {
        return false;
    }
    //請求頭初始化
    $request_headers = array();
    $User_Agent = 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31';
    $request_headers[] = 'User-Agent: '. $User_Agent;
    if($header){
        foreach ($header as $v) {
            $request_headers[] = $v;
        }
    }
 
    $request_headers[] = 'Accept: text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
    switch ($method) {
        case "POST":
            $request_headers[] = "X-HTTP-Method-Override: POST";
            break;
        case "PUT":
            $request_headers[] = "X-HTTP-Method-Override: PUT";
            break;
        case "DELETE":
            $request_headers[] = "X-HTTP-Method-Override: DELETE";
            break;
        default:
    }
 
    //格式化發送數據
    if($params) {
        if($method == 'GET'){
            //GET請求
            $url = $url . '?' . http_build_query($params);
        }else{
            if (!$type){
                $params = json_encode($params,JSON_UNESCAPED_UNICODE);
            }
        }
    }
 
    //發送http請求
    $ch = curl_init();
    if($type) {
        curl_setopt($ch, CURLOPT_TIMEOUT, 1);//設置超時時間為1秒,超過1秒則關閉連接
        #curl_setopt($ch, CURLOPT_NOSIGNAL, 1);     //注意,毫秒超時一定要設置這個
        #curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); //超時毫秒,cURL 7.16.2中被加入。從PHP 5.2.3起可使用
    }else{
        curl_setopt($ch, CURLOPT_TIMEOUT, 1500); // 最大執行時間
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1500); // 在嘗試連接時等待的秒數
    }
    curl_setopt($ch, CURLOPT_URL, $url); // 要訪問的地址
    curl_setopt($ch, CURLOPT_HEADER, 0);// 設置是否顯示返回頭信息  1返回 0不返回
    curl_setopt($ch, CURLOPT_NOBODY, 0); //不想在輸出中包含body部分,設置這個選項為一個非零值
    curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // 自動設置Referer
 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//獲取的信息以文件流的形式返回
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);//https 不進行ssl驗證
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);//設置頭信息
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); //設置請求方式
    if($method != 'GET'){
        if($method != 'POST'){
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        }
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    }
 
    //發送請求獲取返回響應
    $result['data'] = curl_exec($ch);
    $result['httpCode'] = curl_getinfo($ch,CURLINFO_HTTP_CODE);
    if(strlen(curl_error($ch))>1){
        $result = false;
    }
    curl_close($ch);
    //var_dump($result);
    return $result;
}

原文鏈接:https://blog.csdn.net/u011477914/article/details/105989536/

注:測試發現 fsockopen 請求執行https時,有兩個亂碼總是:

      1,返回頭中 Content-Encoding: gzip 表示body是gzip壓縮格式的,body需要gzdecode(body)解壓

      2,返回頭中 Transfer-Encoding: chunked  分塊傳輸編碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM