真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么用PHP實(shí)現(xiàn)簡(jiǎn)單的Socks5Server

本篇內(nèi)容主要講解“怎么用PHP實(shí)現(xiàn)簡(jiǎn)單的Socks5 Server”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“怎么用PHP實(shí)現(xiàn)簡(jiǎn)單的Socks5 Server”吧!

創(chuàng)新互聯(lián)是專業(yè)的涉縣網(wǎng)站建設(shè)公司,涉縣接單;提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè),網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行涉縣網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

利用 Phalcon7 的異步功能實(shí)現(xiàn),完整源碼 https://github.com/dreamsxin/cphalcon7/blob/master/examples/async/Socks5Server.php。

concurrency = max(1, $concurrency);
		$this->channel = new \Phalcon\Async\Channel($capacity);
		$this->context = \Phalcon\Async\Context::background();
	}

	public function close(?\Throwable $e = null): void
	{
		$this->count = \PHP_INT_MAX;
		$this->channel->close($e);
	}

	public function submit(callable $work, $socket, ...$args): \Phalcon\Async\Awaitable
	{
		if ($this->count < $this->concurrency) {
			$this->count++;
			Socks5Server::info('Pool count '.$this->count);
			\Phalcon\Async\Task::asyncWithContext($this->context, static function (iterable $it) {
				try {
					foreach ($it as list ($defer, $context, $work, $socket, $args)) {
						try {
							$defer->resolve($context->run($work, $socket, ...$args));
						} catch (\Throwable $e) {
							Socks5Server::err($e->getMessage());
							$defer->fail($e);
						} finally {
						}
					}
				} catch (\Throwable $e) {
					Socks5Server::err($e->getMessage());
				} finally {
					--$this->count;
				}
			}, $this->channel->getIterator());
		}

		$this->channel->send([
			$defer = new \Phalcon\Async\Deferred(),
			\Phalcon\Async\Context::current(),
			$work,
			$socket,
			$args
		]);

		return $defer->awaitable();
	}
}

class Socks5Server
{
	static public $debug = false;
	private $server;

	private $host;
	private $port;

	private $clients;

	public function __construct($host, $port, callable $callback = NULL, int $concurrency = 1, int $capacity = 0)
	{
		$this->host = $host;
		$this->port = $port;
		$this->callback = $callback;
		$this->pool = new Pool($concurrency, $capacity);
	}

	public function start()
	{
		$callback = $this->callback;
		$ws = $this;
		$worker = static function ($socket) use ($ws, $callback) {
			$socket->status = Socks5::STATUS_INIT;
			$socket->is_closing = false;
			try {
				$buffer = '';
				while (!$socket->is_closing && null !== ($chunk = $socket->read())) {

					$buffer .= $chunk;
					switch ($socket->status) {
						case Socks5::STATUS_INIT:
							/**
							 * 協(xié)商版本以及驗(yàn)證方式
							 * +---------+-----------------+------------------+
							 * |協(xié)議版本 |支持的驗(yàn)證式數(shù)量 |驗(yàn)證方式          |
							 * +---------+-----------------+------------------+
							 * |1個(gè)字節(jié)  |1個(gè)字節(jié)          |1種式占一個(gè)字節(jié)   |
							 * +---------+-----------------+------------------+
							 * |0x05     |0x02             |0x00,0x02         |
							 * +---------+-----------------+------------------+
							 */
							/**
							 * 0x00 無驗(yàn)證需求
							 * 0x01 通用安全服務(wù)應(yīng)用程序接口(GSSAPI)
							 * 0x02 用戶名/密碼(USERNAME/PASSWORD)
							 * 0x03 至 X’7F’ IANA 分配(IANA ASSIGNED)
							 * 0x80 至 X’FE’ 私人方法保留(RESERVED FOR PRIVATE METHODS)
							 * 0xFF 無可接受方法(NO ACCEPTABLE METHODS)
							 */
							$authtypes = Socks5::parseAuth($buffer);
							if ($authtypes === false) {
								$socket->is_closing = true;
								break;
							}
							if ($authtypes === true)  { // continue
								break;
							}
							$socket->status = Socks5::STATUS_ADDR;
							$socket->write("\x05\x00"); // TODO: 暫時(shí)
							$buffer = '';
							break;
						case Socks5::STATUS_AUTH:
							
							if ($callback && \is_callable($callback)) {
								// TODO
							}
							break;
						case Socks5::STATUS_ADDR:
							self::info('Socks5::STATUS_ADDR');
							/**
							 * 建立代理連接
							 * +----------+------------+---------+-----------+-----------------------+------------+
							 * |協(xié)議版本  |請(qǐng)求的類型  |保留字段 |地址類型   |地址數(shù)據(jù)               |地址端口    |
							 * +----------+------------+---------+-----------+-----------------------+------------+
							 * |1個(gè)字節(jié)   |1個(gè)字節(jié)     |1個(gè)字節(jié)  |1個(gè)字節(jié)    |變長(zhǎng)                   |2個(gè)字節(jié)     |
							 * +----------+------------+---------+-----------+-----------------------+------------+
							 * |0x05      |0x01        |0x00     |0x01       |0x0a,0x00,0x01,0x0a    |0x00,0x50   |
							 * +----------+------------+---------+-----------+-----------------------+------------+
							 */
							/**
							 * 請(qǐng)求類型
							 * CONNECT : 0x01, 建立代理連接
							 * BIND : 0x02,告訴代理服務(wù)器監(jiān)聽目標(biāo)機(jī)器的連接,也就是讓代理服務(wù)器創(chuàng)建socket監(jiān)聽來自目標(biāo)機(jī)器的連接。FTP這類需要服務(wù)端主動(dòng)聯(lián)接客戶端的的應(yīng)用場(chǎng)景。
							 *     1. 只有在完成了connnect操作之后才能進(jìn)行bind操作
							 *     2. bind操作之后,代理服務(wù)器會(huì)有兩次響應(yīng), 第一次響應(yīng)是在創(chuàng)建socket監(jiān)聽完成之后,第二次是在目標(biāo)機(jī)器連接到代理服務(wù)器上之后。
							 * UDP ASSOCIATE : 0x03, udp 協(xié)議請(qǐng)求代理。
							 */
							if (strlen($buffer) < 2) {
								break;
							}
							$cmd = ord($buffer[1]);
							if ($cmd != Socks5::CMD_CONNECT) {
								self::err("Bad command ".$cmd);
								$socket->is_closing = true;
								break;
							}
							$headers = Socks5::parseAddr($buffer);
							if (!$headers)  {
								self::err('Error header');
								$socket->is_closing = true;
								break;
							}
							if ($headers === true)  { // continue
								break;
							}
							/**
							 * 數(shù)據(jù)包轉(zhuǎn)發(fā)
							 * +----+------+------+----------+----------+----------+
							 * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
							 * +----+------+------+----------+----------+----------+
							 * | 2  |  1   |  1   | Variable |    2     | Variable |
							 * +----+------+------+----------+----------+----------+
							 */
							$buffer = substr($buffer, $headers[3]);
							$socket->status  = Socks5::STATUS_CONNECTING;
							if (!in_array($headers[0], [Socks5::TYPE_IPV4, Socks5::TYPE_HOST, Socks5::TYPE_IPV6])) {
								self::err('Addr type error');
								$socket->is_closing = true;
								break;
							}
							$tls = NULL;
							if ($headers[2] == 443) {
								$tls = new \Phalcon\Async\Network\TlsClientEncryption();
								$tls = $tls->withAllowSelfSigned(true);
							}
							$socket->client = \Phalcon\Async\Network\TcpSocket::connect($headers[1], $headers[2], $tls);
							$socket->write(Socks5::REPLY_ADDR);
							$socket->status  = Socks5::STATUS_STREAM;
	
							\Phalcon\Async\Task::async(function ($client) use ($socket) {
								while (!$socket->is_closing && null !== ($chunk = $client->read())) {
									$socket->write($chunk);
								}
							}, $socket->client);
							break;
						case Socks5::STATUS_STREAM:
							self::info('Socks5::STATUS_STREAM');
							$socket->client->write($buffer);
							$buffer = '';
							break;
					}
				}
			} catch (\Throwable $e) {
				self::err($e->getMessage());
			} finally {
				$socket->close();
			}
		};

		try {
			$this->server = \Phalcon\Async\Network\TcpServer::listen($this->host, $this->port);
			echo Phalcon\Cli\Color::info('start server listen:'.$this->host.':'.$this->port).PHP_EOL;
			while (true) {
				$socket = $this->server->accept();
				if ($socket === false) {
					continue;
				}
				$this->pool->submit($worker, $socket);
			}
		} catch (\Throwable $e) {
			self::err($e->getMessage());
		} finally {
			if ($this->server) {
				$this->server->close();
			}
		}

	}

	static public function info($message)
	{
		if (self::$debug) {
			echo Phalcon\Cli\Color::info($message).PHP_EOL;
		}
	}

	static public function err($message)
	{
		echo Phalcon\Cli\Color::error($message).PHP_EOL;
	}
}



$opts = new \Phalcon\Cli\Options('Websocket CLI');
$opts->add([
    'type' => \Phalcon\Cli\Options::TYPE_STRING,
    'name' => 'server',
    'shortName' => 's',
    'required' => false, // 可選,需要用=號(hào)賦值
	'help' => "address"
]);
$opts->add([
    'type' => \Phalcon\Cli\Options::TYPE_INT,
    'name' => 'port',
    'shortName' => 'p',
    'required' => false,
	'help' => "port"
]);
$opts->add([
    'type' => \Phalcon\Cli\Options::TYPE_BOOLEAN,
    'name' => 'concurrency',
    'shortName' => 'c',
    'required' => false
]);
$opts->add([
    'type' => \Phalcon\Cli\Options::TYPE_BOOLEAN,
    'name' => 'capacity',
    'shortName' => 'C',
    'required' => false
]);
$opts->add([
    'type' => \Phalcon\Cli\Options::TYPE_BOOLEAN,
    'name' => 'debug',
    'shortName' => 'v',
    'required' => false,
	'help' => "enable debug"
]);
$vals = $opts->parse();
if ($vals === false ) {
	exit;
}
/**
 * 運(yùn)行 php websocket-server.php
 */
if (isset($vals['debug'])) {
	Socks5Server::$debug = true;
	echo Phalcon\Cli\Color::info('Use debug mode').PHP_EOL;
}
$sserver = new Socks5Server(\Phalcon\Arr::get($vals, 'server', '0.0.0.0'), \Phalcon\Arr::get($vals, 'port', 10002), function($socket, $status, $data) {
	// TODO
}, \Phalcon\Arr::get($vals, 'concurrency', 500), \Phalcon\Arr::get($vals, 'capacity', 1));
$sserver->start();

到此,相信大家對(duì)“怎么用PHP實(shí)現(xiàn)簡(jiǎn)單的Socks5 Server”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


文章題目:怎么用PHP實(shí)現(xiàn)簡(jiǎn)單的Socks5Server
URL標(biāo)題:http://weahome.cn/article/gdcgpj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部