用workerman做一个tcp代理

作者: 白云飞 分类: workerman 发布时间: 2017-05-19 17:42 阅读:

最近遇到一个问题,希望游戏客户端不要直接链接服务器,在真实服务器前做一个反向代理,从而对客户端进行过滤,保护主服务器不被攻击。那我们该怎么通过workerman去实现这种架构呢?

思路很简单:
就是 做一个 代理服务器,代理服务器启动之后,去链接真实的 服务器。当代理服务器收到消息之后,将消息转发给真实服务器,同时 代理服务器 也维持了与真实服务器的链接,当真实服务器有消息返回时,将消息推送给客户端即可。

先展示一下,真个架构的文件结构:

server.php 模拟真实的服务器,proxy.php 是代理服务器, client.php 模拟客户端。废话少说,看代码吧:

server.php

<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';

// 创建一个Worker监听2347端口,不使用任何应用层协议
$tcp_worker = new Worker("tcp://0.0.0.0:1090");

// 启动4个进程对外提供服务
$tcp_worker->count = 4;

// 当客户端发来数据时
$tcp_worker->onMessage = function($connection, $data)
{
	echo "proxy server ip : " . $connection->getRemoteip() . PHP_EOL;
	echo "get data : " . $data . PHP_EOL;
    // 向客户端发送hello $data
    $connection->send('hello client');
};

// 运行worker
Worker::runAll();

 

proxy.php

<?php 
use \Workerman\Worker;
use \Workerman\WebServer;
use \Workerman\Connection\TcpConnection;
use \Workerman\Connection\AsyncTcpConnection;

// 自动加载类
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('tcp://0.0.0.0:1080');

// 启动4个进程对外提供服务
$woker->count = 4;

$connection_to_server = null;

$worker->onConnect = function($connection)
{
    global $connection_to_server;
    // 链接真实服务器
    $connection_to_server = new AsyncTcpConnection('tcp://127.0.0.1:1090');
    
    // 接到真实服务器响应信息,返回给客户端
    $connection_to_server->onMessage = function($connection_to_server, $buffer) use ($connection)
    {
       echo 'from server :' . $buffer . PHP_EOL;
       $connection->send('from server :' . $buffer);
    };

    $connection_to_server->onClose = function($connection_to_server)
    {
        echo "connection closed\n";
    };

    $connection_to_server->onError = function($connection_to_server, $code, $msg)
    {
        echo "Error code:$code msg:$msg\n";
    };
    
    $connection_to_server->connect();
};

// 收到客户的信息,传送给服务器
$worker->onMessage = function($connection, $buffer)
{
    echo "client ip is: " . $connection->getRemoteip() . PHP_EOL;
    global $connection_to_server;
    echo "from client " . $buffer . PHP_EOL;
    $connection_to_server->send('from client ' . $buffer);
};

Worker::runAll();

 

client.php

<?php
/**
 * author: NickBai
 * createTime: 2016/12/17 0017 下午 3:00
 */
use \Workerman\Worker;
use \Workerman\Connection\AsyncTcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

$task = new Worker();

$task->onWorkerStart = function($task)
{
    // 链接代理
    $connection_to_proxy = new AsyncTcpConnection('tcp://127.0.0.1:1080');
    // 当连接建立成功时,发送tcp请求数据
    $connection_to_proxy->onConnect = function($connection_to_proxy)
    {
        echo "connect success\n";
        $connection_to_proxy->send("i am client");
    };

    $connection_to_proxy->onMessage = function($connection_to_proxy, $buffer)
    {
       echo "get message from server " . $buffer;
    };

    $connection_to_proxy->onClose = function($connection_to_proxy)
    {
        echo "connection closed\n";
    };

    $connection_to_proxy->onError = function($connection_to_proxy, $code, $msg)
    {
        echo "Error code:$code msg:$msg\n";
    };
    
    $connection_to_proxy->connect();
};

// 运行worker
Worker::runAll();

注意启动顺序 server --- proxy --- client
测试如下:

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。