• 基于Swoole的HTTP/HTTPS代理


    N行代码实现一个简单的代理服务器

    <?php
    /**
     * Web代理服务器(支持http/https)
     * @author zhjx922
     */
    class WebProxyServer
    {
        private $_client = [];
        private $_server;
    
        /**
         * 日志打印
         * @author zhjx922
         * @param string $message
         */
        protected function log($message)
        {
            echo $message . PHP_EOL;
        }
    
        /**
         * 获取代理ip
         * @author zhjx922
         */
        protected function getLocalIp()
        {
            //获取代理IP
            $ipList = swoole_get_local_ip();
            foreach($ipList as $interface => $ip) {
                $this->log("{$interface}:{$ip}");
            }
        }
    
        /**
         * 初始化
         * @author zhjx922
         */
        protected function init()
        {
            $this->getLocalIp();
    
            $this->_server = new swoole_server("0.0.0.0", 8889);
    
            $this->_server->set([
                'buffer_output_size' => 64 * 1024 *1024, //必须为数字
            ]);
        }
    
        /**
         * 跑起来
         * @author zhjx922
         */
        public function run()
        {
            $this->init();
    
            $this->_server->on('connect', function ($server, $fd){
                $this->log("Server connection open: {$fd}");
            });
    
            $this->_server->on('receive', function ($server, $fd, $reactor_id, $buffer){
    
                //判断是否为新连接
                if(!isset($this->_client[$fd])) {
                    //判断代理模式
                    list($method, $url) = explode(' ', $buffer, 3);
                    $url = parse_url($url);
    
                    //ipv6为啥外面还有个方括号?
                    if(strpos($url['host'], ']')) {
                        $url['host'] = str_replace(['[', ']'], '', $url['host']);
                    }
    
                    //解析host+port
                    $host = $url['host'];
                    $port = isset($url['port']) ? $url['port'] : 80;
    
                    //ipv4/v6处理
                    $tcpMode = strpos($url['host'], ':') !== false ? SWOOLE_SOCK_TCP6 : SWOOLE_SOCK_TCP;
                    $this->_client[$fd] = new swoole_client($tcpMode, SWOOLE_SOCK_ASYNC);
    
                    if($method == 'CONNECT')
                    {
                        $this->_client[$fd]->on("connect", function (swoole_client $cli) use ($fd) {
                            $this->log("隧道模式-连接成功!");
                            //告诉客户端准备就绪,可以继续发包
                            $this->_server->send($fd, "HTTP/1.1 200 Connection Established
    
    ");
                        });
                    } else {
                        $this->_client[$fd]->on("connect", function(swoole_client $cli) use ($buffer) {
                            $this->log("正常模式-连接成功!");
                            //直接转发数据
                            $cli->send($buffer);
                        });
                    }
    
                    $this->_client[$fd]->on("receive", function(swoole_client $cli, $buffer) use ($fd){
                        //将收到的数据转发到客户端
                        if($this->_server->exist($fd)) {
                            $this->_server->send($fd, $buffer);
                        }
                    });
    
                    $this->_client[$fd]->on("error", function(swoole_client $cli) use ($fd){
                        $this->log("Client {$fd} error");
                    });
    
                    $this->_client[$fd]->on("close", function(swoole_client $cli) use ($fd){
                        $this->log("Client {$fd} connection close");
                    });
    
                    $this->_client[$fd]->connect($host, $port);
                } else {
                    //已连接,正常转发数据
                    if($this->_client[$fd]->isConnected()) {
                        $this->_client[$fd]->send($buffer);
                    }
                }
    
            });
    
            $this->_server->on('close', function ($server, $fd) {
                $this->log("Server connection close: {$fd}");
                unset($this->_client[$fd]);
            });
    
            $this->_server->start();
        }
    }
    
    
    $server = new WebProxyServer();
    $server->run();
  • 相关阅读:
    MVC EF 修改 封装类 通用泛型方法(一)
    泛型方法动态生成表达式树 Expression
    SEO 优化,网站推广优化教程100条(SEO,网站关键字优化,怎么优化网站,如何优化网站关键字)
    NPOI mvc easyui 根据Excel模板 生成Excel
    A generic error occurred in GDI+. 上传图片报错
    bootstrap-wysiwyg 结合 base64 解码 .net bbs 图片操作类 (三) 图片裁剪
    jquery.validate 验证(支持前台js验证通过,然后ajax后台数据校验)二
    jquery.validate 验证(支持前台js验证通过,然后ajax后台数据校验)
    Font-Awesome 体验 鼠标进入图标变大
    .net cookie
  • 原文地址:https://www.cnblogs.com/twodog/p/12137512.html
Copyright © 2020-2023  润新知