100行PHP代码实现socks5代理服务器
<p style="text-align: left; padding-bottom: 0px; widows: 1; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 8px 0px; padding-left: 0px; letter-spacing: 0px; padding-right: 0px; font: 12px/22px 'Microsoft YaHei',Verdana,sans-serif,宋体; word-wrap: break-word; white-space: normal; color: rgb(51,51,51); word-break: break-all; word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px">前两天在B站上看到一个小伙纸100元组装个电脑打LOL画质流畅,突发奇想100行代码能(简单)实现个啥好玩的。我主要是做php开发的,于是就有了本文。 <p style="text-align: left; padding-bottom: 0px; widows: 1; text-transform: none; background-color: rgb(255,51); word-break: break-all; word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px">当然,由于php(不算swoole扩展)本身不擅长做网络服务端编程,所以这个代理,只是个玩具,离日常使用有点距离。如果想使用稳定可靠的加密(所以能禾斗学上网)代理,可以用这个:<a style="padding-bottom: 0px; margin: 0px; outline-style: none; outline-color: invert; padding-left: 0px; outline-width: 0px; padding-right: 0px; color: rgb(255,131,115); font-size: 12px; padding-top: 0px" href="https://github.com/momaer/asocks-go">https://github.com/momaer/asocks-go也是100来行代码使用go实现。 <p style="text-align: left; padding-bottom: 0px; widows: 1; text-transform: none; background-color: rgb(255,51); word-break: break-all; word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px">写的过程中发现php多线程还是难的。比如我开始想每个连接新建一个线程。但这个线程得保存起来(比如保存到数组),比如官方例子中的这个:<a style="padding-bottom: 0px; margin: 0px; outline-style: none; outline-color: invert; padding-left: 0px; outline-width: 0px; padding-right: 0px; color: rgb(255,115); font-size: 12px; padding-top: 0px" href="https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php">https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php<span class="Apple-converted-space">要放到$clients这个数组里,不然,你试试(curl -L一个要301的地址)就知道出现什么情况了。 <p style="text-align: left; padding-bottom: 0px; widows: 1; text-transform: none; background-color: rgb(255,51); word-break: break-all; word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px">这个例子说了in the real world,do something here to ensure clients not running are destroyed 但是,如何把不再运行的连接销毁却没有讲。恩。我试了把$clients放到一个类里,把类传给线程类,然后在线程类要结束时把$clients里对应的连接给unset掉,无果。 <p style="text-align: left; padding-bottom: 0px; widows: 1; text-transform: none; background-color: rgb(255,51); word-break: break-all; word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px">那,以下就是使用线程池来实现的代理,按道理讲,退出时池要shutdown(),监听socket也要shutdown的,但百行代码,就不勉强了,随着ctrl + c,就让操作系统来回收资源吧。 <p style="text-align: left; padding-bottom: 0px; widows: 1; text-transform: none; background-color: rgb(255,51); word-break: break-all; word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px">php不擅长网络编程体现在哪里呢?首先我用的是stream_socket_XXX相关的函数,为啥不用socket扩展呢?因为socket扩展有问题,参见:<a style="padding-bottom: 0px; margin: 0px; outline-style: none; outline-color: invert; padding-left: 0px; outline-width: 0px; padding-right: 0px; color: rgb(255,115); font-size: 12px; padding-top: 0px" href="https://github.com/krakjoe/pthreads/issues/581">https://github.com/krakjoe/pthreads/issues/581<span class="Apple-converted-space">而stream_set_timeout对stream_socket_recvfrom这些高级操作,不起作用,参见:<a style="padding-bottom: 0px; margin: 0px; outline-style: none; outline-color: invert; padding-left: 0px; outline-width: 0px; padding-right: 0px; color: rgb(255,115); font-size: 12px; padding-top: 0px" href="http://php.net/manual/en/function.stream-set-timeout.php">http://php.net/manual/en/function.stream-set-timeout.php<span class="Apple-converted-space">而这些,在写代理时都需要考虑的。比如连接远程目标服务器时,没有超时控制,很容易就线程池跑满了。 <p style="text-align: left; padding-bottom: 0px; widows: 1; text-transform: none; background-color: rgb(255,51); word-break: break-all; word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px">测试的话,使用curl即可,对了,目前只支持远程dns解析,为啥呢?因为这个玩具后期可是要实现禾斗学上网的哟: curl --socks5-hostname 127.0.0.1:1080<span class="Apple-converted-space"><a style="padding-bottom: 0px; margin: 0px; outline-style: none; outline-color: invert; padding-left: 0px; outline-width: 0px; padding-right: 0px; color: rgb(255,115); font-size: 12px; padding-top: 0px" href="http://ip.cn/">http://ip.cn <div class="jb51code"> <pre class="brush:php;"> 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 function run()
} class ProxyWorker extends Worker $server = stream_socket_server('tcp://0.0.0.0:1080',$errno,$errstr); $pipePool = new Pool(200,Worker::class); for( ; ; ) {
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |