[PHP] 비동기 POST 방식으로 웹 주소에 값 보내고 결과값 받기 (file_get_contents, fsockopen, curl)

(1) file_get_contents, fsockopen

  file_get_contents 함수를 써서 POST 방식으로 매개 변수들의 값을 전달하는 방법이다. (비동기 방식)

$data = array('title' => $post_title, 'num' => $post_number);
$url = 'https://www...';
$options = array( 'http' => array( 'header' => "Content-type: application/x-www-form-urlencoded\r\n", 'method' => 'POST', 'content' => http_build_query($data, '' , '&'),
'timeout' => 60 ) ); $context = stream_context_create($options); $result = file_get_contents($url, false, $context);

  읽을 웹 주소의 통신 규약(프로토콜)이 'https'여도 $options에 넣는 'http'는 그대로 'http'를 쓴다.

  file_get_contents 함수로 바깥의 다른 웹 서버에 자료를 보내려면, 자료를 받는 웹 서버의 allow_url_fopen 기능이 켜져 있어야 한다. allow_url_fopen은 아래의 php.ini 내용으로 켜고 끌 수 있는데, 보안 문제 때문에 되도록 끄는 것을 권장한다.

; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
; https://php.net/allow-url-fopen
allow_url_fopen = Off

  allow_url_fopen 기능을 막으면 file_get_contents 함수를 쓸 수 없다. 조금 다른 방법으로 소켓 기능(fsocketopen)을 쓰는 대안은 있다. 그에 관하여 참고할 수 있는 정보들이 다음 글들에 있다.

// 2022.11.30 fsockopen 함수를 쓴 부호글 상자 더함
$data = array('title' => $post_title, 'num' => $post_number);
$url = 'https://www...';

$parts = parse_url($url);

if(is_array($parts) && isset($parts['query'])) $post_string = $parts['query'];
else $post_string = http_build_query($data, '' , '&');

$fp = fsockopen(($parts['scheme'] == 'https' ? 'ssl://' : '').$parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 60);

$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if(isset($post_string)) $out.= $post_string;

fwrite($fp, $out);
fclose($fp);

(2) curl

  curl 기능을 쓰는 방법도 POST 방식으로 쓸 수 있고 비동기 방식이다.주1 file_get_contents를 쓰는 것보다 빠르고 기능이 더 많다. allow_url_fopen을 막았더라도 쓸 수 있다.

$data = array('title' => $post_title, 'num' => $post_number);
$url = 'https://www...';
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 요청 결과를 문자열로 받음 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // curl이 첫 응답 시간에 대한 timeout
curl_setopt($ch, CURLOPT_TIMEOUT, 60); // curl 전체 실행 시간에 대한 timeout
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 원격 서버의 인증서가 유효한지 검사하지 않음 $result = curl_exec($ch); // 요청 결과 curl_close($ch);

  요청 결과를 받지 않아도 된다면, 'CURLOPT_RETURNTRANSFER'를 false로 바꾸고 '$result = curl_exec($ch);'를 'curl_exec($ch);'로 바꾸어도 된다.

  CURLOPT_CONNECTTIMEOUT은 처음으로 응답을 받기까지 기다리는 시간(단위: 초)이다.

  전체 요청 시간이 CURLOPT_TIMEOUT을 넘기면 전체 작업을 강제로 끝낸다. CURLOPT_TIMEOUT은 file_get_contents 함수에서 넣는 timeout과 같다.

〈주석〉
  1. PHP가 curl 라이브러리를 통한 비동기 처리를 제대로 지원하지 않는다고 한다. (참고: PHP에서 cURL을 비동기로 사용하기) curl_multi 함수를 쓰면 비동기 처리를 할 수 있다. back
글 걸기 주소 : 이 글에는 글을 걸 수 없습니다.

덧글을 달아 주세요