• 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
    ";
        $out .= "HOST: ".$host."
    ";
        if ($method == "POST") {
            $out .= "Content-Length:".strlen($query)."
    ";
        }
        $out .= "Accept: application/json, text/plain, */*
    ";
        $out .= "Access-Control-Allow-Credentials: true
    ";
        $out .= "Content-Type: application/x-www-form-urlencoded
    ";
        $out .= "Cookie: ".$cookie."
    ";
        $out .= "Connection: Close
    
    ";
        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  分块传输编码

  • 相关阅读:
    TAM实施范例
    xmanager连接到RHEL6.
    TAM安装过程中遇到的问题
    db29.1FP2升级FP12
    WAS常见问题及解答
    在 Lotus Quickr for Domino 环境中使用 Tivoli Access Manager WebSEAL 作为反向代理服务器
    TAM包含的内容全面的指南自IBM
    Setting up the Web Admin Tool in LDAP 6.x to communicate via SSL
    oracle字符集。
    redhat中设置环境变量PATH的方法和只显示目录的Tree
  • 原文地址:https://www.cnblogs.com/7qin/p/13296532.html
Copyright © 2020-2023  润新知