100多行PHP代碼實現socks5Proxy 伺服器[2]

來源:互聯網
上載者:User
100多行PHP代碼實現socks5Proxy 伺服器,這次是使用swoole純非同步來寫,使用狀態機器來處理資料。目前用它訪問開源中國木有壓力,但訪問網易新聞就壓力山大。我發現我用別的語言寫得代理,訪問網易新聞都壓力大。嘎嘎,學藝不精。
對swoole理解不深,不知道怎麼處理socket shutdown只關閉讀/寫這樣,還有就是連線逾時,讀寫逾時這種怎麼處理。在網上看到作者說要用定時器,感覺好麻煩,所以,這次的代理,雖然個人用,一般不會有什麼問題,但離產品級的代理,還有段路要走。
如果要利用多核,就使用process模式,設定worker個數為cpu數量即可。
<?phpclass Client{ public $connected = true; public $data = ''; public $remote = null; public $status = 0;}class Server{ public $clients = []; public function start() {  $server = new swoole_server('0.0.0.0', 8388, SWOOLE_BASE, SWOOLE_SOCK_TCP);  $server->set([   'max_conn' => 1000,    'daemonize' => 1,   'reactor_num' => 1,   'worker_num' => 1,   'dispatch_mode' => 2,   'buffer_output_size' => 128 * 1024 * 1024,   'open_cpu_affinity' => 1,   'open_tcp_nodelay' => 1,   'log_file' => 'socks5_server.log',  ]);  $server->on('connect', [$this, 'onConnect']);  $server->on('receive', [$this, 'onReceive']);  $server->on('close', [$this, 'onClose']);  $server->start(); } public function onConnect($server, $fd, $fromID) {  $this->clients[$fd] = new Client(); } public function onReceive($server, $fd, $fromID, $data) {  ($this->clients[$fd])->data .= $data;  $this->parse($server, $fd);  } public function onClose($server, $fd, $fromID) {  $client = $this->clients[$fd];  $client->connected = false; } private function parse($server, $fd)  {  $client = $this->clients[$fd];  switch ($client->status) {   case 0: {    if (strlen($client->data) >= 2) {     $request = unpack('c*', substr($client->data, 0, 2));     if ($request[1] !== 0x05) {      echo '協議不正確:' . $request[1], PHP_EOL;      $server->close($fd);      break;     }     $nmethods = $request[2];     if (strlen($client->data) >= 2 + $nmethods) {      $client->data = substr($client->data, 2 + $nmethods);      $server->send($fd, "\x05\x00");      $client->status = 1;     }    }   }   case 1: {    if (strlen($client->data) < 5)     break;    $request = unpack('c*', $client->data);    $aType = $request[4];    if ($aType === 0x03) { // domain     $domainLen = $request[5];     if (strlen($client->data) < 5 + $domainLen + 2) {       break;      }     $domain = substr($client->data, 5, $domainLen);     $port = unpack('n', substr($client->data, 5 + $domainLen, 2))[1];      $client->data = substr($client->data, 5 + $domainLen + 2);    } else if ($aType === 0x01) { // ipv4     $domain = long2ip(unpack('N', substr($client->data, 4, 4))[1]);     $port = unpack('n', substr($client->data, 8, 2))[1];      $client->data = substr($client->data, 10);    } else {     echo '不支援的atype:' . $aType, PHP_EOL;     $server->close($fd);     break;    }    $remote = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);    $remote->on('connect', function($cli) use($client, $server, $fd, $remote) {     $server->send($fd, "\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00");     $client->status = 2;     $client->remote = $remote;    });    $remote->on("error", function(swoole_client $cli) use($server, $fd) {     //$server->send($fd, ""); // todo 串連不上remote     echo 'connect to remote error.', PHP_EOL;     $server->close($fd);    });    $remote->on('receive', function($cli, $data) use($server, $fd, $client) {     if (!$client->connected) {      echo 'connection has been closed.', PHP_EOL;      return;     }     $server->send($fd, $data);    });    $remote->on('close', function($cli) use($server, $fd, $client) {     $client->remote = null;    });    if ($aType === 0x03) {     swoole_async_dns_lookup($domain, function($host, $ip) use($remote, $port, $server, $fd) {      //todo 當host為空白時的處理。貌似不存在的網域名稱都解析成了原生外網ip,奇怪      if (empty($ip) || empty($host)) {       echo "host:{$host}, ip:{$ip}\n";       $server->close($fd);       return;      }      $remote->connect($ip, $port);     });    } else {     $remote->connect($domain, $port);    }   }   case 2: {    if (strlen($client->data) === 0) {     break;    }    if ($client->remote === null) {     echo 'remote connection has been closed.', PHP_EOL;     break;    }    $sendByteCount = $client->remote->send($client->data);    if ($sendByteCount === false || $sendByteCount < strlen($client->data)) {     echo 'data length:' , strlen($client->data), ' send byte count:', $sendByteCount, PHP_EOL;      echo $client->data, PHP_EOL;     $server->close($fd);     }    $client->data = '';   }  } }}(new Server())->start();

以上就介紹了100多行PHP代碼實現socks5Proxy 伺服器[2],包括了socks5Proxy 伺服器方面的內容,希望對PHP教程有興趣的朋友有所協助。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.