最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

100行PHP代碼實(shí)現(xiàn)socks5代理服務(wù)器

 更新時(shí)間:2016年04月28日 10:17:58   作者:秣馬兒  
這個(gè)例子說了in the real world, do something here to ensure clients not running are destroyed 但是,如何把不再運(yùn)行的連接銷毀卻沒有講。恩。我試了把$clients放到一個(gè)類里,把類傳給線程類,然后在線程類要結(jié)束時(shí)把$clients里對(duì)應(yīng)的連接給unset掉,無果。

前兩天在B站上看到一個(gè)小伙紙100元組裝個(gè)電腦打LOL畫質(zhì)流暢,突發(fā)奇想100行代碼能(簡(jiǎn)單)實(shí)現(xiàn)個(gè)啥好玩的。我主要是做php開發(fā)的,于是就有了本文。

當(dāng)然,由于php(不算swoole擴(kuò)展)本身不擅長(zhǎng)做網(wǎng)絡(luò)服務(wù)端編程,所以這個(gè)代理,只是個(gè)玩具,離日常使用有點(diǎn)距離。如果想使用穩(wěn)定可靠的加密(所以能禾斗學(xué)上網(wǎng))代理,可以用這個(gè):https://github.com/momaer/asocks-go也是100來行代碼使用go實(shí)現(xiàn)。

寫的過程中發(fā)現(xiàn)php多線程還是難的。比如我開始想每個(gè)連接新建一個(gè)線程。但這個(gè)線程得保存起來(比如保存到數(shù)組),比如官方例子中的這個(gè):https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php 要放到$clients這個(gè)數(shù)組里,不然,你試試(curl -L一個(gè)要301的地址)就知道出現(xiàn)什么情況了。

這個(gè)例子說了in the real world, do something here to ensure clients not running are destroyed 但是,如何把不再運(yùn)行的連接銷毀卻沒有講。恩。我試了把$clients放到一個(gè)類里,把類傳給線程類,然后在線程類要結(jié)束時(shí)把$clients里對(duì)應(yīng)的連接給unset掉,無果。

那,以下就是使用線程池來實(shí)現(xiàn)的代理,按道理講,退出時(shí)池要shutdown(),監(jiān)聽socket也要shutdown的,但百行代碼,就不勉強(qiáng)了,隨著ctrl + c,就讓操作系統(tǒng)來回收資源吧。

php不擅長(zhǎng)網(wǎng)絡(luò)編程體現(xiàn)在哪里呢?首先我用的是stream_socket_XXX相關(guān)的函數(shù),為啥不用socket擴(kuò)展呢?因?yàn)閟ocket擴(kuò)展有問題,參見:https://github.com/krakjoe/pthreads/issues/581 而stream_set_timeout對(duì)stream_socket_recvfrom這些高級(jí)操作,不起作用,參見:http://php.net/manual/en/function.stream-set-timeout.php 而這些,在寫代理時(shí)都需要考慮的。比如連接遠(yuǎn)程目標(biāo)服務(wù)器時(shí),沒有超時(shí)控制,很容易就線程池跑滿了。

測(cè)試的話,使用curl即可,對(duì)了,目前只支持遠(yuǎn)程dns解析,為啥呢?因?yàn)檫@個(gè)玩具后期可是要實(shí)現(xiàn)禾斗學(xué)上網(wǎng)的喲: curl --socks5-hostname 127.0.0.1:1080 http://ip.cn

Class Pipe extends Threaded
{
  private $client;
  private $remote;
  public function __construct($client, $remote) 
  {
    $this->client = $client;
    $this->remote = $remote; 
  }
  public function run()
  {
    for ( ; ; ) {
        $data = stream_socket_recvfrom($this->client, 4096);
        if ($data === false || strlen($data) === 0) {
          break;
        } 
        $sendBytes = stream_socket_sendto($this->remote, $data);
        if ($sendBytes <= 0) {
          break;
        }
    }
    stream_socket_shutdown($this->client, STREAM_SHUT_RD);
    stream_socket_shutdown($this->remote, STREAM_SHUT_WR);
  }
}

Class Client extends Threaded
{
  public $fd;
  public function __construct($fd)
  {
    $this->fd = $fd; 
  }

  public function run()
  {
    $data = stream_socket_recvfrom($this->fd, 2);
    $data = unpack('c*', $data);
    if ($data[1] !== 0x05) {
      stream_socket_shutdown($this->fd, STREAM_SHUT_RDWR);
      echo '協(xié)議不正確.', PHP_EOL;
      return;
    }
    $nmethods = $data[2];
    $data = stream_socket_recvfrom($this->fd, $nmethods);
    stream_socket_sendto($this->fd, "\x05\x00");
    $data = stream_socket_recvfrom($this->fd, 4);
    $data = unpack('c*', $data);
    $addressType = $data[4];
    if ($addressType === 0x03) { // domain
      $domainLength = unpack('c', stream_socket_recvfrom($this->fd, 1))[1];
      $data = stream_socket_recvfrom($this->fd, $domainLength + 2);
      $domain = substr($data, 0, $domainLength);
      $port = unpack("n", substr($data, -2))[1];
    } else {
      stream_socket_shutdown($this->fd, STREAM_SHUT_RDWR);
      echo '請(qǐng)使用遠(yuǎn)程dns解析.', PHP_EOL;
    }

    stream_socket_sendto($this->fd, "\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00");
    echo "{$domain}:{$port}", PHP_EOL;
    $remote = stream_socket_client("tcp://{$domain}:{$port}");
    if ($remote === false) {
      stream_socket_shutdown($this->fd, STREAM_SHUT_RDWR);
      return;
    }

    $pool = $this->worker->pipePool;

    $pipe1 = new Pipe($remote, $this->fd);
    $pipe2 = new Pipe($this->fd, $remote);

    $pool->submit($pipe1);
    $pool->submit($pipe2);
  }
}

class ProxyWorker extends Worker
{
  public $pipePool;
  public function __construct($pipePool)
  {
    $this->pipePool = $pipePool;
  }
}

$server = stream_socket_server('tcp://0.0.0.0:1080', $errno, $errstr);
if ($server === false)
  exit($errstr);

$pipePool = new Pool(200, Worker::class);
$pool = new Pool(50, 'ProxyWorker', [$pipePool]);

for( ; ; ) {
  $fd = @stream_socket_accept($server, 60);
  if ($fd === false)
    continue;
  $pool->submit(new Client($fd));
}

相關(guān)文章

  • php輕松實(shí)現(xiàn)文件上傳功能

    php輕松實(shí)現(xiàn)文件上傳功能

    這篇文章主要介紹了php輕松實(shí)現(xiàn)文件上傳功能的全部代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-03-03
  • 部署PHP時(shí)的4個(gè)配置修改說明

    部署PHP時(shí)的4個(gè)配置修改說明

    這篇文章主要介紹了部署PHP時(shí)的4個(gè)配置修改說明,非常重要的四點(diǎn)配置修改,希望大家認(rèn)真閱讀本文。
    2015-10-10
  • php生成并下載word文件到本地實(shí)現(xiàn)方法詳解

    php生成并下載word文件到本地實(shí)現(xiàn)方法詳解

    要給最常用出租屋管理系統(tǒng)增加個(gè)合同功能,mark下知識(shí)點(diǎn)。要生成合同就需要使用phpword。文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • php下Memcached入門實(shí)例解析

    php下Memcached入門實(shí)例解析

    這篇文章主要介紹了php下Memcached入門實(shí)例,較為詳細(xì)的分析了memcached的概念與用法,是非常實(shí)用的技巧,需要的朋友可以參考下
    2015-01-01
  • php常用字符串查找函數(shù)strstr()與strpos()實(shí)例分析

    php常用字符串查找函數(shù)strstr()與strpos()實(shí)例分析

    這篇文章主要介紹了php常用字符串查找函數(shù)strstr()與strpos(),結(jié)合具體實(shí)例形式分析了php字符串查找函數(shù)strstr()與strpos()的具體功能、用法、區(qū)別及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2019-06-06
  • PHP連接sql server 2005環(huán)境配置及問題解決

    PHP連接sql server 2005環(huán)境配置及問題解決

    這篇文章主要介紹了PHP連接sql server 2005環(huán)境配置及問題解決,需要的朋友可以參考下
    2014-08-08
  • 一款簡(jiǎn)單實(shí)用的php操作mysql數(shù)據(jù)庫(kù)類

    一款簡(jiǎn)單實(shí)用的php操作mysql數(shù)據(jù)庫(kù)類

    這篇文章主要介紹了一款簡(jiǎn)單實(shí)用的php操作mysql數(shù)據(jù)庫(kù)類,不但包含了php針對(duì)mysql數(shù)據(jù)庫(kù)的常見操作之外,還有針對(duì)危險(xiǎn)字符的過濾功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-12-12
  • C#靜態(tài)方法與非靜態(tài)方法實(shí)例分析

    C#靜態(tài)方法與非靜態(tài)方法實(shí)例分析

    這篇文章主要介紹了C#靜態(tài)方法與非靜態(tài)方法,重點(diǎn)講述了靜態(tài)方法的實(shí)際應(yīng)用,有助于進(jìn)一步加深對(duì)C#程序設(shè)計(jì)的理解,需要的朋友可以參考下
    2014-09-09
  • php array_map()函數(shù)實(shí)例用法

    php array_map()函數(shù)實(shí)例用法

    在本篇文章里小編給大家分享了一篇關(guān)于php array_map()函數(shù)實(shí)例用法,有興趣的朋友們可以學(xué)習(xí)下。
    2021-03-03
  • 淺談PHP中JSON數(shù)據(jù)操作

    淺談PHP中JSON數(shù)據(jù)操作

    本文的知識(shí)點(diǎn):1、JSON數(shù)據(jù)格式介紹,2、對(duì)數(shù)據(jù)編碼成JSON格式,3、對(duì)JSON數(shù)據(jù)進(jìn)行解碼,并操作,有需要的小伙伴可以參考下。
    2015-07-07

最新評(píng)論

晋州市| 湟中县| 长春市| 永泰县| 武强县| 石台县| 安龙县| 平和县| 子长县| 和田市| 木兰县| 巨野县| 屏山县| 汉阴县| 呼图壁县| 乳山市| 虞城县| 邛崃市| 疏勒县| 门头沟区| 昌邑市| 阳信县| 报价| 高碑店市| 新邵县| 东阿县| 福海县| 江永县| 太康县| 嘉兴市| 宣威市| 德江县| 义乌市| 东方市| 泗水县| 祥云县| 保亭| 府谷县| 镇雄县| 历史| 中江县|