stream_socket_client() 경고에 대한 수정을 하고 싶습니다.
본문
아래의 소스는 온라인 문의가 들어왔을 때 관리자에게 문자를 보내는 코드중 일부입니다.
php 5인 서버를 사용할 때는 에러메세지가 나오지 않았는데
php 7인 서버를 사용중인 지금은 에러메시지가 나옵니다. (이전 서버와 현서버의 차이가 php 버전뿐이라 이렇게 짐작하고 있습니다.)
이 코드를 사용하면 아래의 소스중 빨간 색 라인에서 에러가 나오는데 어떻게 수정해야할지
고수님들에게 도움을 요청드립니다.
참고로 에러메세지는 나오는데 문자메세지의 발송은 잘 되고 있습니다.
Warning: stream_socket_client(): php_network_getaddresses: getaddrinfo failed: Name or service not known in /home/cunet/public_html/bbs/online_update.php on line 115
Warning: stream_socket_client(): unable to connect to ssl://www.k-db.kr:20443 (php_network_getaddresses: getaddrinfo failed: Name or service not known) in /home/cunet/public_html/bbs/online_update.php on line 115
Warning: fwrite() expects parameter 1 to be resource, bool given in /home/cunet/public_html/bbs/online_update.php on line 116
Warning: fread() expects parameter 1 to be resource, bool given in /home/cunet/public_html/bbs/online_update.php on line 118
Warning: fclose() expects parameter 1 to be resource, bool given in /home/cunet/public_html/bbs/online_update.php on line 122
--- 에러가 나는 부분 ---
$h=stream_socket_client($host_url);
fwrite($h,$post);
for($a=0,$r='';!$a;) {
$b=fread($h,8192);
$r.=$b;
$a=(($b=='')?1:0);
}
fclose($h);
return $r;
전체소스---
function post($host,$query,$method='POST') {
$ref_url = ($_SERVER["HTTPS"])?"https://":"http://";
$ref_url .= $_SERVER['HTTP_HOST'];
//echo $host;
$url = parse_url($host);
if(!$url['scheme']) {
$host = "http://$host";
$url = parse_url($host);
}
if($url['scheme']=="https") $host_url = "ssl://$url[host]";
else $host_url = "tcp://$url[host]";
if($url['port']) $host_url .= ":$url[port]";
elseif($url['scheme']=="https") $host_url .= ":443";
else $host_url .= ":80";
if($url['query']==NULL) $path = $url['path'];
else $path = "$url[path]?$url[query]";
$post="$method $path HTTP/1.1\r\nHost: $url[host]\r\nReferer: $ref_url\r\nContent-type: application/x-www-form-urlencoded\r\n${others}User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36\r\nContent-length: ".strlen($query)."\r\nConnection: close\r\n\r\n$query";
$h=stream_socket_client($host_url);
fwrite($h,$post);
for($a=0,$r='';!$a;) {
$b=fread($h,8192);
$r.=$b;
$a=(($b=='')?1:0);
}
fclose($h);
return $r;
}
미리 감사드립니다. (^^)(__)
!-->답변 3
PHP 7에서는 stream_socket_client() 사용 시
도메인 이름 확인 및 네트워크 주소 변환 문제로 인해
php_network_getaddresses: getaddrinfo failed 오류가 발생할 수 있음.
- 네트워크 문제,
- 도메인 네임 서버(DNS) 해석 문제,
- stream_socket_client()의 오류 처리 부족 등의 문제일 가능성이 있음.
※ 수정 방안 :
*에러 핸들링 추가: stream_socket_client()의 반환값이 false일 경우 예외를 던지도록 수정.
*타임아웃 설정: stream_socket_client() 호출 시 timeout 값을 명시하여
네트워크 문제를 줄임.
*에러 출력: stream_socket_client()의 error_message를 받아 로깅.
*DNS 확인: gethostbyname()을 사용하여 호스트 주소를 직접 확인하고,
IP가 반환되지 않으면 오류를 출력.
※ 코드에서 stream_socket_client() 호출 전 도메인 주소가 올바르게 변환되었는지 확인하고,
실패할 경우 적절한 오류 메시지를 반환하도록 개선 함.
function post($host, $query, $method = 'POST') {
$ref_url = ($_SERVER["HTTPS"]) ? "https://" : "http://";
$ref_url .= $_SERVER['HTTP_HOST'];
$url = parse_url($host);
if (!$url['scheme']) {
$host = "http://$host";
$url = parse_url($host);
}
if ($url['scheme'] == "https") {
$host_url = "ssl://$url[host]";
$port = isset($url['port']) ? $url['port'] : 443;
} else {
$host_url = "tcp://$url[host]";
$port = isset($url['port']) ? $url['port'] : 80;
}
$host_url .= ":$port";
if (empty($url['query'])) {
$path = $url['path'];
} else {
$path = "$url[path]?$url[query]";
}
$post = "$method $path HTTP/1.1\r\n"
. "Host: $url[host]\r\n"
. "Referer: $ref_url\r\n"
. "Content-type: application/x-www-form-urlencoded\r\n"
. "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36\r\n"
. "Content-length: " . strlen($query) . "\r\n"
. "Connection: close\r\n\r\n"
. $query;
// 호스트의 IP 변환 및 확인
$ip = gethostbyname($url['host']);
if ($ip == $url['host']) {
return "Error: Could not resolve host: " . $url['host'];
}
// 타임아웃 및 에러 핸들링 추가
$errstr = "";
$errno = 0;
$h = @stream_socket_client($host_url, $errno, $errstr, 10); // 10초 타임아웃 설정
if (!$h) {
return "Error: stream_socket_client() failed - $errstr ($errno)";
}
fwrite($h, $post);
$r = "";
while (!feof($h)) {
$r .= fread($h, 8192);
}
fclose($h);
return $r;
}
*수정 코드의 주요 개선 사항 :
- stream_socket_client() 호출 전에 gethostbyname($url['host'])를 사용하여
도메인 해석이 가능한지 확인.
- 도메인 해석이 실패할 경우 오류 메시지를 반환하여 추가적인 문제를 방지.
- stream_socket_client()의 timeout을 10초로 설정하여,
응답이 지연될 경우 무한 대기하지 않도록 개선.
- stream_socket_client() 호출 시 발생하는 errno, errstr을 받아서 에러 메시지를 출력.
- @ 연산자를 사용하여 경고를 억제하고, 대신 직접 if (!$h) 조건으로 에러 메시지를 처리.
- 기존 코드에서 $b == ''을 검사하는 대신, 더 안정적인 feof($h)로 루프를 종료하도록 수정.
stream_socket_client 부분을 수정해보세요.
$context = stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
]
]);
$h = stream_socket_client($host_url, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);