Jadual Kandungan
代理开始批量验证中,整个过程将会花费您几分钟时间。

多线程的cURL

Jul 25, 2016 am 08:49 AM

本处是一个可以灵活的多线程的调用 cURL的。
这里跟php手册 http://us2.php.net/manual/zh/function.curl-multi-select.php 中提供的样例不同,代码执行效率要高不少
本处两个文件,一个是muti_curl的文件,里面包含两个class
一个是运用的方法,这里是批量检查代理ip是否可用
  1. class request_setting {
  2. public $url = false;
  3. public $method = 'GET';
  4. public $post_data = null;
  5. public $headers = null;
  6. public $options = null;
  7. function __construct($url, $method = "GET", $post_data = null, $headers = null, $options = null) {
  8. $this->url = $url;
  9. $this->method = $method;
  10. $this->post_data = $post_data;
  11. $this->headers = $headers;
  12. $this->options = $options;
  13. }
  14. public function __destruct() {
  15. unset($this->url, $this->method, $this->post_data, $this->headers, $this->options);
  16. }
  17. }
  18. /***********************************************************************************************
  19. 批量操作的类
  20. *******************************************************************************************/
  21. class muti_curl {
  22. protected $thread_size = 100;
  23. protected $timeout = 30;
  24. private $callback;
  25. protected $options = array(
  26. CURLOPT_SSL_VERIFYPEER => false,//禁用后cURL将终止从服务端进行验证。使用CURLOPT_CAINFO选项设置证书使用CURLOPT_CAPATH选项设置证书目录 如果CURLOPT_SSL_VERIFYPEER(默认值为2)被启用,CURLOPT_SSL_VERIFYHOST需要被设置成TRUE否则设置为FALSE。 自cURL 7.10开始默认为TRUE。从cURL 7.10开始默认绑定安装。
  27. CURLOPT_RETURNTRANSFER => true, //将 curl_exec()获取的信息以文件流的形式返回,而不是直接输
  28. CURLOPT_CONNECTTIMEOUT => 15,
  29. CURLOPT_TIMEOUT => 30,
  30. // CURLOPT_HTTP_VERSION=>CURL_HTTP_VERSION_1_0, //使用代理的时候用这个去抓取数据,更爽
  31. // CURLOPT_AUTOREFERER=>false,// 当根据Location:重定向时,自动设置header中的Referer:信息。
  32. // CURLOPT_BINARYTRANSFER=>false, //在启用CURLOPT_RETURNTRANSFER的时候,返回原生的(Raw)输出这个不用设置。
  33. // CURLOPT_COOKIESESSION=>true,// 启用时curl会仅仅传递一个session cookie,忽略其他的cookie,默认状况下cURL会将所有的cookie返回
  34. // CURLOPT_CRLF=>false,// 启用时将Unix的换行符转换成回车换行符。
  35. // CURLOPT_DNS_USE_GLOBAL_CACHE=>false, // 启用时会启用一个全局的DNS缓存,此项为线程安全的,并且默认启用。
  36. // CURLOPT_FAILONERROR=>false, // 显示HTTP状态码,默认行为是忽略编号小于等于400的HTTP信息。
  37. // CURLOPT_FILETIME=>true, //启用时会尝试修改远程文档中的信息。结果信息会通过 curl_getinfo()函数的CURLINFO_FILETIME选项返回。 curl_getinfo().
  38. // CURLOPT_FOLLOWLOCATION=>false, // 启用时会将服务器服务器返回的"Location: "放在header中递归的返回给服务器,使用CURLOPT_MAXREDIRS可以限定递归返回的数量。
  39. // CURLOPT_FORBID_REUSE=>true, //在完成交互以后强迫断开连接,不能重用。
  40. // CURLOPT_FRESH_CONNECT=>true,// 强制获取一个新的连接,替代缓存中的连接。
  41. // CURLOPT_FTP_USE_EPRT=>false,// 启用时当FTP下载时,使用EPRT (或 LPRT)命令。设置为FALSE时禁用EPRT和LPRT,使用PORT命令 only.
  42. // CURLOPT_FTP_USE_EPSV=>false,// 启用时,在FTP传输过程中回复到PASV模式前首先尝试EPSV命令。设置为FALSE时禁用EPSV命令。
  43. // CURLOPT_FTPAPPEND=>false,// 启用时追加写入文件而不是覆盖它。
  44. // CURLOPT_FTPASCII=>false,// CURLOPT_TRANSFERTEXT的别名。
  45. // CURLOPT_FTPLISTONLY=>false,// 启用时只列出FTP目录的名字。
  46. // CURLOPT_HEADER=>true,// 启用时会将头文件的信息作为数据流输出。
  47. // CURLINFO_HEADER_OUT=>false, //启用时追踪句柄的请求字符串。
  48. // CURLOPT_HTTPGET=>true,// 启用时会设置HTTP的method为GET,因为GET是默认是,所以只在被修改的情况下使用。
  49. // CURLOPT_HTTPPROXYTUNNEL =>true,// 启用时会通过HTTP代理来传输。
  50. // CURLOPT_MUTE=>true,// 启用时将cURL函数中所有修改过的参数恢复默认值。
  51. // CURLOPT_NETRC=>false,// 在连接建立以后,访问~/.netrc文件获取用户名和密码信息连接远程站点。
  52. // CURLOPT_NOBODY=>true, 启用时将不对HTML中的BODY部分进行输出。
  53. // CURLOPT_NOPROGRESS=>false,//启用时关闭curl传输的进度条,此项的默认设置为启用。
  54. // CURLOPT_NOSIGNAL=>false,// 启用时忽略所有的curl传递给php进行的信号。在SAPI多线程传输时此项被默认启用。 cURL 7.10时被加入。
  55. // CURLOPT_POST=>false,// 启用时会发送一个常规的POST请求,类型为:application/x-www-form-urlencoded,就像表单提交的一样。
  56. // CURLOPT_PUT=>false,// 启用时允许HTTP发送文件,必须同时设置CURLOPT_INFILE和CURLOPT_INFILESIZE。
  57. // CURLOPT_TRANSFERTEXT=>false,// 启用后对FTP传输使用ASCII模式。对于LDAP,它检索纯文本信息而非HTML。在Windows系统上,系统不会把STDOUT设置成binary模式。
  58. // CURLOPT_UNRESTRICTED_AUTH=>true,// 在使用CURLOPT_FOLLOWLOCATION产生的header中的多个locations中持续追加用户名和密码信息,即使域名已发生改变。
  59. // CURLOPT_UPLOAD=>false,// 启用后允许文件上传。
  60. // CURLOPT_VERBOSE =>true,// 启用时会汇报所有的信息,存放在STDERR或指定的CURLOPT_STDERR中。
  61. );
  62. private $headers = array();
  63. private $requests = array();
  64. private $requestMap = array();
  65. /*********************
  66. 构造一个callback的函数
  67. ********************/
  68. function __construct($callback = null) {
  69. $this->callback = $callback;
  70. }
  71. /********************************************************************
  72. 重载 __get的方法
  73. *******************************************************************/
  74. public function __get($name) {
  75. return (isset($this->{$name})) ? $this->{$name} : null;
  76. }
  77. /*********************************************************************
  78. 重载 __set的方法
  79. *******************************************************/
  80. public function __set($name, $value) {
  81. // 增加一个设置到headers
  82. if ($name == "options" || $name == "headers") {
  83. $this->{$name} = $value + $this->{$name};
  84. } else {
  85. $this->{$name} = $value;
  86. }
  87. return true;
  88. }
  89. //增加一个请求
  90. public function add($request) {
  91. $this->requests[] = $request;
  92. return true;
  93. }
  94. public function request($url, $method = "GET", $post_data = null, $headers = null, $options = null) {
  95. $this->requests[] = new request_setting($url, $method, $post_data, $headers, $options);
  96. return true;
  97. }
  98. public function get($url, $headers = null, $options = null) {
  99. return $this->request($url, "GET", null, $headers, $options);
  100. }
  101. public function post($url, $post_data = null, $headers = null, $options = null) {
  102. return $this->request($url, "POST", $post_data, $headers, $options);
  103. }
  104. private function single_curl() {
  105. $ch = curl_init(); //初始化
  106. $request = array_shift($this->requests);//把第一个单元移出并作为结果
  107. $options = $this->get_options($request);//获得该单元的设置
  108. curl_setopt_array($ch, $options);//批设置
  109. $output = curl_exec($ch);
  110. $curl_info = curl_getinfo($ch);
  111. if ($this->callback) {
  112. $callback = $this->callback;
  113. if (is_callable($this->callback)) {
  114. call_user_func($callback, $output, $curl_info, $request);
  115. }
  116. }
  117. else
  118. return $output;
  119. return true;
  120. }
  121. private function rolling_curl($thread_size = null) {
  122. if ($thread_size){
  123. $this->thread_size = $thread_size;
  124. }
  125. if (count($this->requests) thread_size){
  126. $this->thread_size = count($this->requests);
  127. }
  128. if ($this->thread_size $errorinfo = '线程大小必须大于 1!!!!';
  129. throw new Exception($errorinfo);
  130. }
  131. $queue = curl_multi_init();
  132. //在线程里开始增加任务队列
  133. for ($i = 0; $i thread_size; $i++) {
  134. $ch = curl_init();
  135. $options = $this->get_options($this->requests[$i]);
  136. curl_setopt_array($ch, $options);//获得设置
  137. curl_multi_add_handle($queue, $ch);//添加进去
  138. $key = (string) $ch;
  139. $this->requestMap[$key] = $i;
  140. }
  141. do {
  142. while (($statu_run_muti_exec = curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM) ;
  143. if ($statu_run_muti_exec != CURLM_OK){ break; }
  144. // 发现完成的一个请求,进行处理
  145. while ($done = curl_multi_info_read($queue)) {
  146. $curl_info = curl_getinfo($done['handle']);
  147. $output = curl_multi_getcontent($done['handle']);
  148. $callback = $this->callback;
  149. if (is_callable($callback)){
  150. $key = (string) $done['handle'];
  151. $request = $this->requests[$this->requestMap[$key]];
  152. unset($this->requestMap[$key]);//这个销毁变量用得很帅
  153. call_user_func($callback, $output, $curl_info, $request);
  154. }
  155. //增加一个未处理的请求加入到一个已经完成的队列中
  156. if ($i requests) && isset($this->requests[$i]) && $i requests)) {
  157. $ch = curl_init();
  158. $options = $this->get_options($this->requests[$i]);
  159. curl_setopt_array($ch, $options);
  160. curl_multi_add_handle($queue, $ch);
  161. $key = (string) $ch;
  162. $this->requestMap[$key] = $i;
  163. $i++;
  164. }
  165. curl_multi_remove_handle($queue, $done['handle']);
  166. echo "done ";
  167. print_r($queue);
  168. print_r ($done);
  169. }
  170. // 这一步非常非常重要如果有一个完成后,要重新设置设置timeout的时间
  171. //这里很关键的一点,就是要保证第一次所有的线程里的请求最少有一个是有效的,否则就出现第一次所有的都没有效果,导致 $active=0,因此不执行下面的东西
  172. if ($active >0){
  173. curl_multi_select($queue, $this->timeout);
  174. }
  175. } while ($active);
  176. curl_multi_close($queue);
  177. return true;
  178. }
  179. public function execute($thread_size = null) {
  180. //判断thread_size的大小如果只有一个请求,就用单线程模式
  181. if (count($this->requests) == 1) {
  182. return $this->single_curl();
  183. } else {
  184. return $this->rolling_curl($thread_size);
  185. }
  186. }
  187. private function get_options($request) {
  188. $options = $this->__get('options');
  189. if (ini_get('safe_mode') == 'Off' || !ini_get('safe_mode')) {
  190. // $options[CURLOPT_FOLLOWLOCATION] = 1;
  191. // $options[CURLOPT_MAXREDIRS] = 5;
  192. }
  193. $headers = $this->__get('headers');
  194. if ($request->options) {
  195. $options = $request->options + $options;
  196. }
  197. $options[CURLOPT_URL] = $request->url;
  198. //下面分别对post选项与header选项进行设置
  199. if ($request->post_data){
  200. $options[CURLOPT_POST] = 1;
  201. $options[CURLOPT_POSTFIELDS] = $request->post_data;
  202. }
  203. if ($headers) {
  204. $options[CURLOPT_HEADER] = 0;
  205. $options[CURLOPT_HTTPHEADER] = $headers;
  206. }
  207. return $options;
  208. }
  209. public function __destruct() {
  210. unset($this->thread_size, $this->callback, $this->options, $this->headers, $this->requests);
  211. }
  212. }
  213. ?>
复制代码
  1. header("content-type:text/html; charset=utf-8");
  2. require("muti_curl_class.php");
  3. set_time_limit(0);
  4. $sucesesnum=0;
  5. $good_proxy=array();
  6. function request_callback($response, $info, $request) {
  7. global $sucesesnum,$good_proxy;
  8. // 下面的正则可以对返回的结果进行选择性显示
  9. /* if (preg_match("~(.*?)~i", $response, $out)) {
  10. $title = $out[1];
  11. }*/
  12. // echo '
    '.$response .'
    ';
  13. echo '
    ';
  14. //对响应也就是 $response 进行检测判断里面是否有设定的字符,如果有判断运用该代理成功
  15. if( $response !== false && substr_count($response, 'User-agent: Baiduspider') >=1 ) {
  16. // $result = true;
  17. echo "true
    ";
  18. // echo $request[options][10004];
  19. // print_r ($request->options);
  20. echo $request->options[CURLOPT_PROXY];
  21. $good_proxy[]=$request->options[CURLOPT_PROXY];
  22. }
  23. echo '
    the-->'. $sucesesnum.'// print_r ($request);
  24. //echo $request->url;
  25. $sucesesnum++;
  26. echo "
    ";
  27. }
  28. $params = array_merge($_GET, $_POST); //此处获得传递过来的代理ip的地址
  29. $result = $proxy_ip = trim($params['ip']);
  30. $timeout=intval(trim($params['timeout']));
  31. if($timeoutif($timeout>300){$timeout=300;}
  32. $thread_size=intval(trim($params['thread_size']));
  33. if($thread_sizeif($thread_size>300){$thread_size =300;}
  34. if($proxy_ip == '') {
  35. echo '请输入IP!!';
  36. return;
  37. }
  38. $replace_arr1 = array(' ', 'qq代理:', 'dn28.com', 'qqip', 'qq代理', 'qq代理ip', '代理ip:', 'ip:', '代理ip','"',"'",'\\','/',' ');
  39. $result = str_replace($replace_arr1, array(''), $result);
  40. $result = str_replace(",", "\n", $result);
  41. $resArr = explode("\n", $result);
  42. foreach($resArr as $k => $v) {
  43. $posProxy = getPos($v, '@');
  44. if($posProxy===false){
  45. if (!empty($v)){$proxyip_and_port = $v; }
  46. }else{
  47. $proxyip_and_port = substr($v, 0, $posProxy);
  48. }
  49. $newRes[] =trim($proxyip_and_port);
  50. }
  51. print_r($newRes);
  52. //die();
  53. $option_setting = array(
  54. CURLOPT_SSL_VERIFYPEER => 0,
  55. CURLOPT_RETURNTRANSFER => true,
  56. CURLOPT_CONNECTTIMEOUT => 5,
  57. CURLOPT_TIMEOUT => 30,
  58. CURLOPT_HEADER=>false,
  59. CURLOPT_PROXY=>'',//这个地方设置代理的位置
  60. );
  61. $url= 'http://www.baidu.com/robots.txt';
  62. $btime=time();
  63. $rc = new muti_curl("request_callback");
  64. $rc->timeout = $timeout;
  65. $rc->thread_size = $thread_size;
  66. foreach ($newRes as $v) {
  67. $option_setting[CURLOPT_PROXY]=$v;
  68. $request = new request_setting($url, $method = "GET", $post_data = null,$header= null, $option_setting);
  69. $rc->add($request);
  70. }
  71. $rc->execute();
  72. $etime=time();
  73. $usedtime=$etime-$btime;
  74. echo 'all'. $sucesesnum.'use'. $usedtime;
  75. echo '
    ';
  76. $good_proxy= array_unique($good_proxy);
  77. $str='';
  78. foreach ($good_proxy as $v){
  79. $str.="'".trim($v)."',";
  80. }
  81. $str= str_replace ( ' ' , '' ,$str );
  82. $str = preg_replace('/\s+/', ' ', $str);
  83. echo $str.'
    ';
  84. var_export ($good_proxy);
  85. //var_dump ($good_proxy);
  86. //**************************************************************************************************
  87. //*******************************只用了一个函数
  88. function parseProxyInfo ( $proxyStr ) {
  89. //$proxyStr = '202.115.207.25:80@HTTP;四川省成都市 四川师范大学';
  90. $posIp = getPos($proxyStr, ':');
  91. $ip = substr($proxyStr, 0, $posIp);
  92. $posPort = getPos($proxyStr, '@');
  93. $port = substr($proxyStr, $posIp+1, $posPort-$posIp-1);
  94. $posType = getPos($proxyStr, ';');
  95. $type = substr($proxyStr, $posPort+1, $posType-$posPort-1);
  96. $location = substr(strstr($proxyStr, ';'), 1);
  97. return array(
  98. 'ip' => $ip,
  99. 'port' => $port,
  100. 'type' => $type,
  101. 'location' => $location
  102. );
  103. }
  104. function getPos($haystack, $needle){
  105. return strpos($haystack, $needle);
  106. }
  107. function check_proxy_is_useful($model, $proxy_info_arr = array()) {
  108. global $params, $config;
  109. if($model == 'single') {
  110. $proxy_port = intval(trim($params['port']));
  111. $check_proxy_url = $config['verify_url'];
  112. $proxy_time_out = intval(trim($params['timeout']));
  113. $retry = intval(trim($params['retry']));
  114. $proxy_ip = trim($params['ip']);
  115. $proxy = new proxy( $proxy_ip, $proxy_port, $check_proxy_url, $proxy_time_out, $retry );
  116. //成功返回string success, 失败返回boolean false
  117. $result = $proxy -> check_proxy();
  118. //var_dump($result);
  119. $proxy_str_success = ''.$proxy_ip.':'.$proxy_port.'@'.'HTTP 代理验证成功!';
  120. $proxy_str_failed = ''.$proxy_ip.':'.$proxy_port.'@'.'HTTP 代理验证失败!';
  121. return $result !== false ? $proxy_str_success : $proxy_str_failed;
  122. } elseif ($model == 'collect') {
  123. $proxy_port = intval(trim($proxy_info_arr['port']));
  124. $check_proxy_url = $config['verify_url'];
  125. $proxy_time_out = intval(trim($params['timeout']));
  126. $retry = intval(trim($params['retry']));
  127. $proxy_ip = trim($proxy_info_arr['ip']);
  128. /*echo $proxy_ip.'
    ';
  129. echo $proxy_port.'
    ';
  130. echo $check_proxy_url.'
    ';
  131. echo $proxy_time_out.'
    ';
  132. echo $retry.'
    ';*/
  133. if(!isset($proxy)) {
  134. $proxy = new proxy( $proxy_ip, $proxy_port, $check_proxy_url, $proxy_time_out, $retry );
  135. }
  136. //成功返回string success, 失败返回boolean false
  137. $result = $proxy -> check_proxy();
  138. return $result;
  139. }
  140. }
  141. function get_single(){
  142. global $params, $config;
  143. $proxy_ip = trim($params['ip']);
  144. if($proxy_ip == '') {
  145. echo '请输入IP!!';
  146. return;
  147. }
  148. echo check_proxy_is_useful('single');
  149. }
  150. function get_proxy_by_collect(){
  151. global $params, $config;
  152. $params['url'] = trim($params['url']);
  153. if($params['url'] == '') {
  154. echo '请输入url!';
  155. return;
  156. }
  157. //$url = 'http://www.dn28.com/html/75/n-5175.html';
  158. $con = iconv('GBK', 'UTF-8', file_get_contents($params['url']));
  159. preg_match ('/(.*)
    /s', $con, $arr);
  160. $result = strip_tags ($arr[1], '
    ');
  161. $replace_arr1 = array(' ', 'qq代理:', 'dn28.com', 'qqip', 'qq代理', 'qq代理ip', '代理ip:', 'ip:', '代理ip');
  162. $result = str_replace($replace_arr1, array(''), $result);
  163. //print_r($arr);
  164. $resArr = explode('
    ', $result);
  165. //print_r($resArr);
  166. echo '

    代理开始批量验证中,整个过程将会花费您几分钟时间。

    ';
  167. unset($_SESSION['success_arr']);
  168. foreach($resArr as $k => $v) {
  169. $newRes[$k] = parseProxyInfo($v);
  170. //print_r($newRes[$k]);
  171. /*return;*/
  172. $result = check_proxy_is_useful('collect', $newRes[$k]);
  173. $proxy_str_success = ''.$newRes[$k]['ip'].':'.$newRes[$k]['port'].'@'.$newRes[$k]['type'].' 代理验证成功!   IP地址:'.$newRes[$k]['location'].'';
  174. $proxy_str_failed = ''.$newRes[$k]['ip'].':'.$newRes[$k]['port'].'@'.$newRes[$k]['type'].' 代理验证失败!   IP地址:'.$newRes[$k]['location'].'';
  175. if($result !== false ){
  176. echo $proxy_str_success;
  177. $_SESSION['success_arr'][] = $success_arr[] = $newRes[$k];
  178. } else {
  179. echo $proxy_str_failed;
  180. }
  181. echo '
    ';
  182. }
  183. if(isset($success_arr) && count($success_arr) > 0 ) {
  184. save_success_proxy($success_arr);
  185. echo '

    [保存验证成功的代理到本地电脑]   [我要看看历史数据]

    ';
  186. } else {
  187. echo '

    [我要看看历史数据]

    ';
  188. }
  189. //print_r($success_arr);
  190. }
  191. function get_proxy_by_rule(){
  192. global $params, $config;
  193. $result = $proxy_ip = trim($params['ip']);
  194. if($proxy_ip == '') {
  195. echo '请输入IP!!';
  196. return;
  197. }
  198. $replace_arr1 = array(' ', 'qq代理:', 'dn28.com', 'qqip', 'qq代理', 'qq代理ip', '代理ip:', 'ip:', '代理ip');
  199. $result = str_replace($replace_arr1, array(''), $result);
  200. $resArr = explode("\n", $result);
  201. //print_r($resArr);
  202. echo '

    代理开始批量验证中,整个过程将会花费您几分钟时间。

    ';
  203. unset($_SESSION['success_arr']);
  204. foreach($resArr as $k => $v) {
  205. $newRes[$k] = parseProxyInfo($v);
  206. //print_r($newRes[$k]);
  207. /*return;*/
  208. $result = check_proxy_is_useful('collect', $newRes[$k]);
  209. //var_dump($result);
  210. $proxy_str_success = ''.$newRes[$k]['ip'].':'.$newRes[$k]['port'].'@'.$newRes[$k]['type'].' 代理验证成功!   IP地址:'.$newRes[$k]['location'].'';
  211. $proxy_str_failed = ''.$newRes[$k]['ip'].':'.$newRes[$k]['port'].'@'.$newRes[$k]['type'].' 代理验证失败!   IP地址:'.$newRes[$k]['location'].'';
  212. if($result !== false ){
  213. echo $proxy_str_success;
  214. $_SESSION['success_arr'][] = $success_arr[] = $newRes[$k];
  215. } else {
  216. echo $proxy_str_failed;
  217. }
  218. echo '
    ';
  219. }
  220. if(isset($success_arr) && count($success_arr) > 0 ) {
  221. save_success_proxy($success_arr);
  222. echo '

    [保存到php格式文件]   [保存验证成功的代理到本地电脑]   [我要看看历史数据]

    ';
  223. } else {
  224. echo '

    [我要看看历史数据]

    ';
  225. }
  226. }
  227. function save_success_proxy($success_arr){
  228. global $config;
  229. date_default_timezone_set('PRC');
  230. $str = '';
  231. foreach($success_arr as $k => $v) {
  232. $str .= $v['ip'].':'.$v['port'].'@'.$v['type'].';'.$v['location']."\n";
  233. }
  234. $fp = fopen($config['root_path'].'/success_proxy/'.date('YmdHi').'.log', 'a+');
  235. fwrite($fp, $str);
  236. fclose($fp);
  237. unset($str);
  238. }
  239. ?>
复制代码


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Jelaskan JSON Web Tokens (JWT) dan kes penggunaannya dalam PHP API. Jelaskan JSON Web Tokens (JWT) dan kes penggunaannya dalam PHP API. Apr 05, 2025 am 12:04 AM

JWT adalah standard terbuka berdasarkan JSON, yang digunakan untuk menghantar maklumat secara selamat antara pihak, terutamanya untuk pengesahan identiti dan pertukaran maklumat. 1. JWT terdiri daripada tiga bahagian: header, muatan dan tandatangan. 2. Prinsip kerja JWT termasuk tiga langkah: menjana JWT, mengesahkan JWT dan muatan parsing. 3. Apabila menggunakan JWT untuk pengesahan di PHP, JWT boleh dijana dan disahkan, dan peranan pengguna dan maklumat kebenaran boleh dimasukkan dalam penggunaan lanjutan. 4. Kesilapan umum termasuk kegagalan pengesahan tandatangan, tamat tempoh, dan muatan besar. Kemahiran penyahpepijatan termasuk menggunakan alat debugging dan pembalakan. 5. Pengoptimuman prestasi dan amalan terbaik termasuk menggunakan algoritma tandatangan yang sesuai, menetapkan tempoh kesahihan dengan munasabah,

Huraikan prinsip -prinsip yang kukuh dan bagaimana ia memohon kepada pembangunan PHP. Huraikan prinsip -prinsip yang kukuh dan bagaimana ia memohon kepada pembangunan PHP. Apr 03, 2025 am 12:04 AM

Penerapan prinsip pepejal dalam pembangunan PHP termasuk: 1. Prinsip Tanggungjawab Tunggal (SRP): Setiap kelas bertanggungjawab untuk hanya satu fungsi. 2. Prinsip Terbuka dan Tutup (OCP): Perubahan dicapai melalui lanjutan dan bukannya pengubahsuaian. 3. Prinsip Penggantian Lisch (LSP): Subkelas boleh menggantikan kelas asas tanpa menjejaskan ketepatan program. 4. Prinsip Pengasingan Antara Muka (ISP): Gunakan antara muka halus untuk mengelakkan kebergantungan dan kaedah yang tidak digunakan. 5. Prinsip Inversi Ketergantungan (DIP): Modul peringkat tinggi dan rendah bergantung kepada abstraksi dan dilaksanakan melalui suntikan ketergantungan.

Bagaimana cara menetapkan kebenaran secara automatik UnixSocket selepas sistem dimulakan semula? Bagaimana cara menetapkan kebenaran secara automatik UnixSocket selepas sistem dimulakan semula? Mar 31, 2025 pm 11:54 PM

Bagaimana untuk menetapkan keizinan UnixSocket secara automatik selepas sistem dimulakan semula. Setiap kali sistem dimulakan semula, kita perlu melaksanakan perintah berikut untuk mengubahsuai keizinan UnixSocket: sudo ...

Bagaimana cara debug mod CLI dalam phpstorm? Bagaimana cara debug mod CLI dalam phpstorm? Apr 01, 2025 pm 02:57 PM

Bagaimana cara debug mod CLI dalam phpstorm? Semasa membangun dengan PHPStorm, kadang -kadang kita perlu debug PHP dalam mod Interface Line Command (CLI) ...

Terangkan konsep pengikatan statik lewat dalam PHP. Terangkan konsep pengikatan statik lewat dalam PHP. Mar 21, 2025 pm 01:33 PM

Artikel membincangkan pengikatan statik lewat (LSB) dalam PHP, yang diperkenalkan dalam Php 5.3, yang membolehkan resolusi runtime kaedah statik memerlukan lebih banyak warisan yang fleksibel. Isu: LSB vs polimorfisme tradisional; Aplikasi Praktikal LSB dan Potensi Perfo

Bagaimana cara menghantar permintaan pos yang mengandungi data JSON menggunakan perpustakaan php curl? Bagaimana cara menghantar permintaan pos yang mengandungi data JSON menggunakan perpustakaan php curl? Apr 01, 2025 pm 03:12 PM

Menghantar data JSON menggunakan perpustakaan Curl PHP dalam pembangunan PHP, sering kali perlu berinteraksi dengan API luaran. Salah satu cara biasa ialah menggunakan perpustakaan curl untuk menghantar post ...

Ciri -ciri Keselamatan Rangka Kerja: Melindungi Kelemahan. Ciri -ciri Keselamatan Rangka Kerja: Melindungi Kelemahan. Mar 28, 2025 pm 05:11 PM

Artikel membincangkan ciri -ciri keselamatan penting dalam rangka kerja untuk melindungi daripada kelemahan, termasuk pengesahan input, pengesahan, dan kemas kini tetap.

See all articles