两个不同的tcp服务如何监听在同一个端口上?

小W

问题描述

目前服务器只开放了一个端口供互联网访问,现在workerman的一个tcp服务已经监听了此端口,如果再使用worker作mysql代理,或者其他方式怎么能实现?

通过nginx tcp代理是否可行

通过客户端链接mysql服务测试打印输出数据,

MySQL客户端发送过来的数据MySQL客户端发送过来的数据

截图

904 1 1
1个回答

walkor

可以用workerman做一个分发代理,监听一个端口,然后onMessage里根据数据格式判断是哪种数据,然后转发到对应的实际端口中。
例如只有一个端口,这个端口既需要转发tcp数据,也需要转发mysql数据(作为mysql代理),假设tcp服务端口是8181,mysql端口是3306,workerman作为代理转发这两种数据给8181和3306端口代码逻辑类似下面这样

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

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

$worker->onMessage = function(TcpConnection $connection, $buffer)
{
    // 如果是mysql数据,转发到本机3306端口 (作为示例is_mysql并未实现)
    if (is_mysql($buffer)) {
        $connection_to_3306 = new AsyncTcpConnection('tcp://127.0.0.1:3306');
        $connection_to_3306->send($buffer);
        $connection->pipe($connection_to_3306);
        $connection_to_3306->pipe($connection);
        $connection_to_3306->connect();
        return;
    }
    // 否则转发到8181端口
    $connection_to_8181 = new AsyncTcpConnection('tcp://127.0.0.1:8181');
    $connection_to_8181->send($buffer);
    $connection->pipe($connection_to_8181);
    $connection_to_8181->pipe($connection);
    $connection_to_8181->connect();
};

// 运行worker
Worker::runAll();
  • 小W 2022-11-26

    也就是只能通过发送数据时区分,connect时无法验证

  • 小W 2022-12-01

    @walkor 大佬,使用你上面的例子,是不是需要通过客户端先连接tcp8080,然后客户端发送连接msg,服务端接收到msg后,再通过数据区分客户端需要连接哪一个服务?

  • 小W 2022-12-01

    那么如何通过$buffer区分tcp服务? 测试mysql连接时,通过客户端发送的数据来看,没有头绪

  • walkor 2022-12-01

    对,上面代理机制需要客户端连8080,然后客户端发送一个数据包,代理判断数据包属于mysql的数据还是你的tcp数据。只需要判断一个数据包即可,后续数据就自动pipe方法就自动代理转发了。
    但是想起来一个问题,mysql客户端连接到mysql服务端后不会主动发数据,要等mysql服务端发送数据后客户端才会发送。所以上面方案应该不行。你的需求应该实现不了。

年代过于久远,无法发表回答
🔝