一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - PHP教程 - 100行PHP代碼實(shí)現(xiàn)socks5代理服務(wù)器

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

2021-01-13 16:59秣馬兒 PHP教程

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

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

當(dāng)然,由于php(不算swoole擴(kuò)展)本身不擅長做網(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里對應(yīng)的連接給unset掉,無果。

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

php不擅長網(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對stream_socket_recvfrom這些高級操作,不起作用,參見:http://php.net/manual/en/function.stream-set-timeout.php 而這些,在寫代理時(shí)都需要考慮的。比如連接遠(yuǎn)程目標(biāo)服務(wù)器時(shí),沒有超時(shí)控制,很容易就線程池跑滿了。

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

?
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
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 '請使用遠(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));
}

 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国内精品国语自产拍在线观看55 | ady久久| 青青青视频蜜桃一区二区 | 91视频a| 情欲满载2012美国dvd | 亚洲国产精品久久卡一 | 高中生放荡日记高h娜娜 | 色戒 完整版 | 久久夜色噜噜噜亚洲AV0000 | 国产卡一卡二卡三卡四 | 国产欧美日韩亚洲精品区2345 | 小兰被扒开内裤露出p | 嫩草影院地址一地址二 | 亚洲午夜精品久久久久久成年 | 欧美最猛性xxxxx动态图 | 久青草国产在视频在线观看 | 免费91麻豆精品国产自产在线观看 | 亚洲成人影院在线观看 | 国产精品久久久久久久久久久久久久 | 97porm国内自拍视频 | 久久综合网久久综合 | 2018天天拍拍拍免费视频 | 激情六月丁香婷婷四房播 | 国产精品女主播大秀在线 | 亚洲视频在线一区二区三区 | 国产这里有精品 | 四虎网站网址 | 特黄特黄一级片 | 日韩精品高清自在线 | 国产性tv国产精品 | 国产精品亚洲va在线观看 | 美女下面揉出水免费视频 | 扒开放荡老师裙子猛烈的进入 | 四虎永久网址影院 | 亚洲国产第一 | 亚洲欧美日韩中文字幕久久 | 国产麻豆剧果冻传媒观看免费视频 | 久久婷婷丁香五月色综合啪免费 | 美艳教师刘艳第三部166 | 亚洲性久久久影院 | 人与善交大片免费看 |