前两天在B站上看到一个小伙纸100元组装个电脑打LOL画质流畅,突发奇想100行代码能(简单)实现个啥好玩的。我主要是做php开发的,于是就有了本文。
当然,由于php(不算swoole扩展)本身不擅长做网络服务端编程,所以这个代理,只是个玩具,离日常使用有点距离。如果想使用稳定可靠的加密(所以能禾斗学上网)代理,可以用这个:https://github.com/momaer/asocks-go也是100来行代码使用go实现。
写的过程中发现php多线程还是难的。比如我开始想每个连接新建一个线程。但这个线程得保存起来(比如保存到数组),比如官方例子中的这个:https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php 要放到$clients这个数组里,不然,你试试(curl -L一个要301的地址)就知道出现什么情况了。
这个例子说了in the real world, do something here to ensure clients not running are destroyed 但是,如何把不再运行的连接销毁却没有讲。恩。我试了把$clients放到一个类里,把类传给线程类,然后在线程类要结束时把$clients里对应的连接给unset掉,无果。
那,以下就是使用线程池来实现的代理,按道理讲,退出时池要shutdown(),监听socket也要shutdown的,但百行代码,就不勉强了,随着ctrl + c,就让操作系统来回收资源吧。
php不擅长网络编程体现在哪里呢?首先我用的是stream_socket_XXX相关的函数,为啥不用socket扩展呢?因为socket扩展有问题,参见:https://github.com/krakjoe/pthreads/issues/581 而stream_set_timeout对stream_socket_recvfrom这些高级操作,不起作用,参见:http://php.net/manual/en/function.stream-set-timeout.php 而这些,在写代理时都需要考虑的。比如连接远程目标服务器时,没有超时控制,很容易就线程池跑满了。
测试的话,使用curl即可,对了,目前只支持远程dns解析,为啥呢?因为这个玩具后期可是要实现禾斗学上网的哟: 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 '协议不正确.', 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 '请使用远程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));
}
100行PHP,socks5
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]