原生php实现代理端口

sunwenzheng

代码如下,php版本7.4.28
我用原生代码写了一个服务端和一个客户端,
服务端是 192.168.3.66 的 3306
客户端连接的 110.242.68.4:80 ,这个就是百度网站的地址
客户端作为服务器的代理工具,做数据转发。

要达到的效果就是 浏览器访问192.168.3.66的3306 等于访问110.242.68.4:80

现在的情况是,如果我在命令行使用nc来访问
nc 192.168.3.66 3306
GET / HTTP/1.1

然后是有正常的返回的。

但是如果用浏览器访问 http://192.168.3.66:3306
网页是不能正常展示的。

请朋友帮我看一下,问题是出在哪里了


<?php
class client
{
    public $client ;
    public $status;
    public $client_id;
    public $event=[];

    public function on($name, $callBack)
    {
        $this->event[$name] = $callBack;
    }

    public function runEvent($eventName, $args)
    {
        if (is_callable($this->event[$eventName])) {
            $this->event[$eventName]($this, ...$args);
        }
    }

    public function __construct($host,$port)
    {
        $this->client = socket_create(AF_INET, SOCK_STREAM, 0);
        $tag = socket_connect($this->client, $host,$port);
        $this->client_id = (int) $this->client;
        if($tag){
            $this->status = 'run';
            socket_set_nonblock($this->client);
        }else{
            die;
        }
    }

    public function write($data)
    {
        socket_write($this->client, $data, strlen($data));
    }

    public function read()
    {
            $len_read = socket_recv($this->client, $string_read, 1024, 0);

            if ($len_read === false) {
            } elseif ($len_read === 0) {
                socket_close($this->client);
                // socket closed
                $this->status = 'close';
                $this->client= null;
                $this->runEvent("close",[]);

            } else {
                $this->runEvent("message", [ $string_read]);
            }

    }
    public  function start()
    {
        $this->runEvent("connect",[]);

    }
}

class Server
{
    public $address;
    public $mainSocket;
    public $event;
    public static $clients = [];
    public  $proxy_list = [];

    public function __construct($address, $port)
    {
        $this->address = $address . ':' . $port;
        $this->mainSocket = socket_create(AF_INET, SOCK_STREAM, 0);
        socket_bind($this->mainSocket, $address, $port);
        socket_listen($this->mainSocket, 1);
        socket_set_nonblock($this->mainSocket);
    }

    public function on($name, $callBack)
    {
        $this->event[$name] = $callBack;
    }

    public function runEvent($eventName, $args)
    {
        if (is_callable($this->event[$eventName])) {
            $this->event[$eventName]($this, ...$args);
        }
    }

    public function accept()
    {
        $clientFd = socket_accept($this->mainSocket);
        if (is_resource($clientFd)) {
            socket_set_nonblock($clientFd);

            $client_id = (int) $clientFd;
            self::$clients[$client_id] = $clientFd;

            $this->runEvent("connect", [$clientFd]);
        }
    }

    public function write($client, $data)
    {
        socket_write($client, $data, strlen($data));
    }

    public function read($client)
    {
        $id = (int) $client;
        $len_read = socket_recv($client, $string_read, 1024, 0);

        if ($len_read === false) {
        } elseif ($len_read === 0) {
            socket_close($client);
            // socket closed
            unset(self::$clients[$id]);
            $this->runEvent("close", [$id]);
        } else {

            $this->runEvent("message", [$client, $string_read]);
        }
    }
    public function start()
    {
        while (1) {
            usleep(1000);

            $read = [$this->mainSocket];
            foreach (self::$clients as $client) {
                $read[] = $client;
            }
            $write = [];
            $error = [];
            socket_select($read, $write, $error, 1);
            if (count($read)) {
                foreach ($read as $readFd) {
                    if ($readFd == $this->mainSocket) {
                        $this->accept();
                    } else {
                        $this->read($readFd);
                    }
                }
            }

            if (count($this->proxy_list)) {
                $read = [];
                foreach ($this->proxy_list as $client) {
                    $read[] = $client->client;
                }
                $write = [];
                $error = [];
                socket_select($read, $write, $error, 1);
                if (count($read)) {
                    foreach ($read as $readFd) {
                        $proxy_id = (int) $readFd;
                        $this->proxy_list[$proxy_id]->read();
                    }
                }
            }
        }
    }
}

$server = new Server('192.168.3.66', '3306');
$server->on('connect', function ($server, $client) {

    // 110.242.68.4:80 这个是百度的网页
    // 要达到的效果就是 访问192.168.3.66的3306 等于访问110.242.68.4:80
    $client2 = new client('110.242.68.4', '80');
    $server->proxy_list[$client2->client_id] = $client2;

    $client2->on('connect', function ($client2) {
    });

    $client2->on('message', function ($client2, $data) use ($server, $client) {
        $data = strtr($data, ['Host: 110.242.68.4:80' => 'Host: 192.168.3.66:3306']);
        $server->write($client, $data);
    });

    $client2->on('close', function ($client2) use ($server, $client) {
        unset($server->proxy_list[$client2->client_id]);
    });

    $server->on('message', function ($server, $client, $data) use ($client2) {
        $data = strtr($data, ['Host: 192.168.3.66:3306' => 'Host: 110.242.68.4:80']);

        $client2->write($data);
    });

    $server->on('close', function ($server, $id) {
    });

    $client2->start();
});

$server->start();
474 0 0
0个回答

🔝