PHP Socket编程 之 fsockopen指定ip获取远程数据 及 301自动跳转
当域名与ip不相符,又无法修改系统hosts时,我们需要指定ip来获取远程数据,通过搜索php curl相关资料,未发现可用方法,故写了如下两个函数。
函数支持get或者post方式,301自动跳转,支持自定义header,仅支持ipv4的http协议。
代码已集成到AlonePHP中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | /* http_get_with_ip,用于ip解析错误或者需要指定ip的时候以get方式获取数据 * @param string $url 远程地址 * @param string $ip 需要访问的ip * @param array $header 需要添加的其它header参数 * @return string|boolean 返回获取的内容,访问失败返回false */ function http_get_with_ip( $url , $ip = '' , $header = array ()) { return curl_post_with_ip( $url , null, $ip , $header ); } /* http_post_with_ip,用于ip解析错误或者需要指定ip的时候以post方式获取数据 * @param string $url 远程地址 * @param array|null $post_data 以post方式提交数据,如果此参数为null,则使用get方式 * @param string $ip 需要访问的ip * @param array $header 需要添加的其它header参数 * @return string|boolean 返回获取的内容,访问失败返回false */ function http_post_with_ip( $url , $post_data = null, $ip = '' , $header = array ()) { /* 最大循环跳转次数 */ $loop_max_count = 5; static $loop_count = 0; $errstr = '' ; $errno = '' ; /* 解析URL */ $url_array = parse_url ( $url ); if ( $url_array === false) { $loop_count = 0; return false; } $host = $url_array [ 'host' ]; /* 域名解析失败则退出 */ if (! $host ) { $loop_count = 0; return false; } /* 获取端口 */ $port = isset( $url_array [ 'port' ]) ? $url_array [ 'port' ] : 80; /* 获取ip */ if ( $ip === '' ) { $ip = gethostbyname ( $host ); } $fp = fsockopen ( $ip , $port , $errno , $errstr , 90); if (! $fp ) { $loop_count = 0; return false; } else { $out = ( is_array ( $post_data ) ? "POST" : "GET" ) . " {$url} HTTP/1.0\r\n" ; /* 最终的header数组 */ $header_result = array (); $header_result [ 'Host' ] = $host ; /* 处理post数据 */ if ( is_array ( $post_data )) { $post_values = array (); foreach ( $post_data as $key => $value ) { array_push ( $post_values , urlencode( $key ) . "=" . urlencode( $value )); } $post_content = implode( "&" , $post_values ); $header_result [ 'Content-type' ] = "application/x-www-form-urlencoded" ; $header_result [ 'Content-length' ] = strlen ( $post_content ); } /* 设置默认的header */ $header_result [ 'User-Agent' ] = "Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0" ; $header_result = array_merge ( $header_result , $header ); /* 载入用户的header */ foreach ( $header_result as $key => $value ) { $out .= $key . ": " . $value . "\r\n" ; } $out .= "Connection: close\r\n\r\n" ; if ( is_array ( $post_data )) { $out .= $post_content ; } fputs ( $fp , $out ); $response = '' ; while (( $line = fread ( $fp , 4096))) { $response .= $line ; } fclose( $fp ); //分离Header头信息 $pos = strpos ( $response , "\r\n\r\n" ); $header_content = substr ( $response , 0, $pos ); $response = substr ( $response , $pos + 4); if (preg_match( "/HTTP\/\d\.\d (\d+) /" , $header_content , $matches ) !== 1) { $loop_count = 0; return false; } $http_status = $matches [1]; /* 如果是30x,就跳转 */ if ( $http_status == 301 || $http_status == 302) { if (preg_match( "/Location:(.*?)\n/" , $header_content , $matches ) !== 1) { $loop_count = 0; return false; } $url = trim( $matches [1]); $loop_count ++; return curl_post_with_ip( $url , $post_data , $ip , $header ); } $loop_count = 0; return $response ; } } |
https://actom.me/blog/php%E4%BD%BF%E7%94%A8fsockopen%E6%8C%87%E5%AE%9Aip%E9%80%9A%E8%BF%87get%E6%88%96%E8%80%85post%E8%8E%B7%E5%8F%96%E8%BF%9C%E7%A8%8B%E6%95%B0%E6%8D%AE.html/comment-page-1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具