PHP的3种发送HTTP请求的方式
Posted 王小麦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP的3种发送HTTP请求的方式相关的知识,希望对你有一定的参考价值。
1.CURL方式发送数据及上传文件
1 <?php 2 3 class IndexController extends ControllerBase 4 { 5 6 public function indexAction() 7 { 8 $url = \'http://192.168.10.168/home/index\'; 9 $data = array( 10 \'name\'=>\'网络开发\', 11 \'address\'=>\'123456789\', 12 //"file" => "@".getcwd()."/temp/test.zip",//要上传的本地文件地址"@"上传时候,上传路径前面要有@符号 13 \'file\' => new cURLFile(getcwd()."/temp/test.zip"), 14 ); 15 16 //没有影响,但是还是有少部分服务器不兼容。本文得出的结论是,在没有需要上传文件的 17 //情况下,尽量对post提交的数据进行http_build_query,然后发送出去,能实现更好的兼容性, 18 $url = $url."?".http_build_query($data); $res = $this->mycurl($url); 19 20 //解析xml 21 //simplexml_load_string($pageContents, \'SimpleXMLElement\', LIBXML_NOCDATA) 22 //$data = json_encode($data); 23 //$res = $this->mycurl($url,$data); 24 var_export($res); 25 } 26 public function mycurl($url, $postfields = NULL, $method=\'POST\'){ 27 //$url = "http://127.0.0.1:8888"; 28 $result = array( \'header\' => \'\', 29 \'body\' => \'\', 30 \'curl_error\' => \'\', 31 \'http_code\' => \'\', 32 \'last_url\' => \'\'); 33 $timeout = 10;//超时时间 34 $connectTimeout = 0;//无限等待 35 $ssl = substr($url, 0, 8) == "https://" ? true : false; 36 $header = array( 37 //"Content-Type: application/x-www-form-urlencoded", 38 "Content-Type: multipart/form-data", 39 "Keep-Alive: 300"); 40 41 //开始curl 42 $ci = curl_init(); 43 //设置curl使用的HTTP协议,CURL_HTTP_VERSION_NONE(让curl自己判断),CURL_HTTP_VERSION_1_0(HTTP/1.0),CURL_HTTP_VERSION_1_1(HTTP/1.1) 44 curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 45 //在HTTP请求中包含一个”user-agent”头的字符串。 46 curl_setopt($ci, CURLOPT_USERAGENT,$_SERVER[\'HTTP_USER_AGENT\']); 47 curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $connectTimeout); //在发起连接前等待的时间,如果设置为0,则无限等待 48 curl_setopt($ci, CURLOPT_TIMEOUT, $timeout); 49 //如果成功只返回TRUE,自动输出返回的内容。如果失败返回FALSE 获取的信息以文件流的形式返回 50 curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE); 51 curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 52 curl_setopt($ci, CURLOPT_AUTOREFERER, 1); // 自动设置Referer 53 //header中“Accept-Encoding: ”部分的内容,支持的编码格式为:"identity","deflate","gzip"。如果设置为空字符串,则表示支持所有的编码格式 54 curl_setopt($ci, CURLOPT_ENCODING, ""); 55 if ($ssl) { 56 curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, 0); // 信任任何证书 浏览器访问https的时候,浏览器会自动加载网站的安全证书进行加密 57 curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, 1); // 检查证书中是否设置域名 从证书中检查SSL加密算法是否存在 58 } 59 //避免data数据过长问题 设置一个header中传输内容的数组 60 curl_setopt($ci, CURLOPT_HTTPHEADER, array(\'Expect:\')); 61 62 //以json方式传输 63 if(!is_array($postfields) && is_string($postfields)){ 64 curl_setopt($ci, CURLOPT_HTTPHEADER, array(\'Content-Type: application/json\',\'Content-Length:\'.strlen($postfields))); 65 } 66 67 //已指定header头格式传输 68 //curl_setopt($ci, CURLOPT_HTTPHEADER, $header); 69 //设置一个回调函数,这个函数有两个参数,第一个是curl的资源句柄,第二个是输出的header数据。header数据的输出必须依赖这个函数,返回已写入的数据大小 70 //如果你想把一个头包含在输出中,设置这个选项为一个非零值。 返回response头部信息 显示返回的Header区域内容 71 curl_setopt($ci, CURLOPT_HEADER, 1); 72 73 switch ($method) { 74 case \'POST\': 75 curl_setopt($ci, CURLOPT_POST, 1);// 发送一个常规的Post请求 76 if (!empty($postfields)) { 77 curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields); 78 } 79 break; 80 case \'DELETE\': 81 curl_setopt($ci, CURLOPT_CUSTOMREQUEST, \'DELETE\'); 82 if (!empty($postfields)) { 83 $url = "{$url}?{$postfields}"; 84 } 85 break; 86 } 87 curl_setopt($ci, CURLOPT_URL, $url); 88 //发送请求的字符串头 89 curl_setopt($ci, CURLINFO_HEADER_OUT, TRUE); 90 91 $response = curl_exec($ci); 92 $error = curl_error($ci); 93 94 //获取http头部信息 95 $response_header_info = curl_getinfo($ci, CURLINFO_HEADER_OUT);// CURLINFO_HEADER_OUT 必须设置成1 才返回 96 $http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE); 97 $result[\'http_code\'] = $http_code; 98 $result[\'last_url\'] = curl_getinfo($ci,CURLINFO_EFFECTIVE_URL); 99 $this->log->info("response_header_info:\\n".$response_header_info); 100 101 //获取错误信息 102 if ( $error != "" ) 103 { 104 $this->log->info("状态码:".$http_code." 发送失败:".json_encode($error)); 105 $result[\'curl_error\'] = $error; 106 $result[\'curl_error_no\'] = curl_errno($ci); 107 curl_close ($ci); 108 return $result; 109 } 110 if( $response ) 111 { 112 $header_size = curl_getinfo($ci,CURLINFO_HEADER_SIZE); 113 $result[\'header\'] = substr($response, 0, $header_size); 114 $result[\'body\'] = substr( $response, $header_size ); 115 $this->log->info("状态码:".$http_code." 成功发送:".json_encode($response)); 116 } 117 curl_close ($ci); 118 return $result; 119 120 } 121 122 }
接受方PHP:receive.php
1 <?php 2 3 class HomeController extends ControllerBase 4 { 5 6 public function indexAction() 7 { 8 9 echo "Success ok!"; 10 if($_GET){ 11 foreach ($_GET as $k =>$v) 12 { 13 $this->log->debug("get----------------$k=$v"); 14 } 15 } 16 //只能接收Content-Type: application/x-www-form-urlencoded提交的数据 17 if($_POST){ 18 foreach ($_POST as $k =>$v) 19 { 20 $this->log->debug("post----------------$k=$v"); 21 } 22 } 23 //方法2、file_get_contents("php://input"); Content-Type: application/json 24 $input = file_get_contents("php://input"); 25 if($input){ 26 $json_data = json_decode($input); 27 if($json_data){ 28 foreach ($json_data as $k =>$v) 29 { 30 $this->log->debug("json_decode----------------$k=$v"); 31 } 32 } 33 $this->log->debug("file_get----------------$input"); 34 } 35 //获取上传文件 36 if($_FILES){ 37 $file = move_uploaded_file($_FILES[\'file\'][\'tmp_name\'], getcwd()."/files/1.rar"); 38 if($file){ 39 echo "保存文件成功"; 40 } 41 } 42 43 } 44 }
2.stream流的方式
stream_context_create — 创建资源流上下文
stream_context_create 作用:创建并返回一个文本数据流并应用各种选项,
可用于 fopen(), file_get_contents() 等过程的超时设置、代理服务器、请求方式、头信息设置的特殊过程。
例子:
<?php function post($url, $data) { $postdata = http_build_query( $data ); $opts = array(\'http\' => array( \'method\' => \'POST\', \'header\' => \'Content-type: application/x-www-form-urlencoded\', \'content\' => $postdata ) ); $context = stream_context_create($opts); $result = file_get_contents($url, false, $context); return $result; }
3.socket方式
使用套接字建立连接,拼接 HTTP 报文发送数据进行 HTTP 请求。
fsockopen — 打开一个网络连接或者一个Unix套接字连接
说明
$hostname
[, int $port
= -1 [, int &$errno
[, string &$errstr
[, float $timeout
= ini_get("default_socket_timeout") ]]]] )初始化一个套接字连接到指定主机(hostname
)。
PHP支持以下的套接字传输器类型列表 所支持的套接字传输器(Socket Transports)列表。也可以通过stream_get_transports()来获取套接字传输器支持类型。
默认情况下将以阻塞模式开启套接字连接。当然你可以通过stream_set_blocking()将它转换到非阻塞模式。
stream_socket_client()与之非常相似,而且提供了更加丰富的参数设置,包括非阻塞模式和提供上下文的的设置。
参数
hostname
-
如果安装了OpenSSL,那么你也许应该在你的主机名地址前面添加访问协议ssl://或者是tls://,从而可以使用基于TCP/IP协议的SSL或者TLS的客户端连接到远程主机。
port
-
端口号。如果对该参数传一个-1,则表示不使用端口,例如unix://。
errno
-
如果传入了该参数,holds the system level error number that occurred in the system-level connect() call。
如果
errno
的返回值为0,而且这个函数的返回值为FALSE
,那么这表明该错误发生在套接字连接(connect())调用之前,导致连接失败的原因最大的可能是初始化套接字的时候发生了错误。 errstr
-
错误信息将以字符串的信息返回。
timeout
-
设置连接的时限,单位为秒。
Note:
注意:如果你要对建立在套接字基础上的读写操作设置操作时间设置连接时限,请使用stream_set_timeout(),fsockopen()的连接时限(
timeout
)的参数仅仅在套接字连接的时候生效。
返回值
fsockopen()将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())。如果调用失败,将返回FALSE
。
<?php $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\\n"; } else { $out = "GET / HTTP/1.1\\r\\n"; $out .= "Host: www.example.com\\r\\n"; $out .= "Connection: Close\\r\\n\\r\\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } ?>
用fsockopen 以post方式获取数据
1 <?php 2 function HTTP_Post($URL,$data,$cookie, $referrer="") 3 { 4 // parsing the given URL 5 $URL_Info=parse_url($URL); 6 // Building referrer 7 if($referrer=="") // if not given use this script as referrer 8 $referrer="111"; 9 // making string from $data 10 foreach($data as $key=>$value) 11 $values[]="$key=".urlencode($value); 12 $data_string=implode("&",$values); 13 // Find out which port is needed - if not given use standard (=80) 14 if(!isset($URL_Info["port"])) 15 $URL_Info["port"]=80; 16 // building POST-request: 17 $request.="POST ".$URL_Info["path"]." HTTP/1.1\\n"; 18 $request.="Host: ".$URL_Info["host"]."\\n"; 19 $request.="Referer: $referer\\n"; 20 $request.="Content-type: application/x-www-form-urlencoded\\n"; 21 $request.="Content-length: ".strlen($data_string)."\\n"; 22 $request.="Connection: close\\n"; 23 $request.="Cookie: $cookie\\n"; 24 $request.="\\n"; 25 $request.=$data_string."\\n"; 26 $fp = fsockopen($URL_Info["host"],$URL_Info["port"]); 27 fputs($fp, $request); 28 while(!feof($fp)) { 29 $result .= fgets($fp, 1024); 30 } 31 fclose($fp); 32 return $result; 33 } 34 ?>
用fsockopen函数打开url,以get方式获取完整的数据,包括header和body,fsockopen需要 PHP.ini 中
allow_url_fopen 选项开启
1 <?php 2 function get_url ($url,$cookie=false) 3 { 4 $url = parse_url($url); 5 $query = $url[path]."?".$url[query]; 6 echo "Query:".$query; 7 $fp = fsockopen( $url[host], $url[port]?$url[port]:80 , $errno, $errstr, 30); 8 if (!$fp) { 9 return false; 10 } else { 11 $request = "GET $query HTTP/1.1\\r\\n"; 12 $request .= "Host: $url[host]\\r\\n"; 13 $request .= "Connection: Close\\r\\n"; 14 if($cookie) $request.="Cookie: $cookie\\n"; 15 $request.="\\r\\n"; 16 fwrite($fp,$request); 17 while()) { 18 $result .= @fgets($fp, 1024); 19 } 20 fclose($fp); 21 return $result; 22 } 23 } 24 //获取url的html部分,去掉header 25 function GetUrlHTML($url,$cookie=false) 26 { 27 $rowdata = get_url($url,$cookie); 28 if($rowdata) 29 { 30 $body= stristr($rowdata,"\\r\\n\\r\\n"); 31 $body=substr($body,4,strlen($body)); 32 return $body; 33 } 34 return false; 35 } 36 ?>
以上是关于PHP的3种发送HTTP请求的方式的主要内容,如果未能解决你的问题,请参考以下文章