當前位置: 妍妍網 > 碼農

Workerman實作Navicat Premium轉發代理

2024-05-30碼農

概述

主要用於代理MySQL連線,用Navicat Premium直接連線資料庫,用不了一會在卡住,用了這個代理就可以流暢使用,也可以用於存取內部資料庫或者服務等等。

計畫倉庫:https://gitee.com/windthesky/forward_proxy.git

配置

全部在 start.php 檔中

<?php
/** @noinspection PhpUnused */
/** @noinspection PhpUndefinedFieldInspection */
/** @noinspection PhpObjectFieldsAreOnlyWrittenInspection */
ini_set('memory_limit''512M');
useWorkerman\Connection\AsyncTcpConnection;
useWorkerman\Worker;
useWorkerman\Connection\TcpConnection;
// 自動載入類
require_once__DIR__ . '/vendor/autoload.php';
require_once__DIR__ . '/common.php';
// 是否寫入日記
const LOG_WRITE = true;
// 是否顯示日記
const SHOW_LOG = true;
// 是否超時關閉
const TIMEOUT_CLOSE = true;
// 超過300秒後發送訊息會先斷開
const TIME = 300;
//接收緩沖區大小,預設2M,根據網速和傳輸數據大小填寫,影響最終轉發的網速
TcpConnection::$defaultMaxSendBufferSize = 2*1024*1024;
AsyncTcpConnection::$defaultMaxSendBufferSize = 2*1024*1024;
$proxy_list = [
[
'type' => 'tcp',
'host' => '127.0.0.1',
'port' => 3306,
'local_port' => 33060,
],
];
$app_list = [];
$connect_list = [];
$client_list = [];
/**
 * app收到
 * @param AsyncTcpConnection $app_connection
 * @param $data
 * @return void
 */

functionapp_message(AsyncTcpConnection $app_connection,$data)void
{
try {
write_log('app收到:開始');
$client_id=$app_connection->client_id;
global $connect_list;
write_log(['app收到:',$data]);
write_log(['app收到-client_id:',$client_id]);
$connect_list[$client_id]->send($data);
write_log('app收到-處理完:');
catch (Throwable $e) {
write_log(['app收到:異常==】',$e->getMessage()]);
$app_connection->close();
}
}
/**
 * app錯誤
 * @param AsyncTcpConnection $app_connection
 * @return void
 */

functionapp_error(AsyncTcpConnection $app_connection)void
{
try {
write_log('app錯誤:');
$client_id=$app_connection->client_id;
global $connect_list;
$connect_list[$client_id]->close();
write_log('app錯誤:執行完');
catch (Throwable $e) {
write_log(['app錯誤:異常==】',$e->getMessage()]);
}
}
/**
 * app關閉
 * @param AsyncTcpConnection $app_connection
 * @return void
 */

functionapp_close(AsyncTcpConnection $app_connection)void
{
try {
write_log('app關閉:');
$client_id=$app_connection->client_id;
global $connect_list,$app_list;
$connect_list[$client_id]->close();
unset($app_list[$client_id]);
write_log('app關閉:執行完');
catch (Throwable $e) {
write_log(['app關閉:異常==】',$e->getMessage()]);
}
}
//Todo 客戶端連線處理
/**
 * 客戶端連線處理
 * @param TcpConnection $connection
 * @return void
 */

functionhandle_connection(TcpConnection $connection)void
{
try {
write_log('客戶端連線:');
$connection->lastMessageTime = time();
global $app_list,$connect_list;
$client_id = 'client-'.session_create_id();
$connection->client_id = $client_id;
$connect_list[$client_id]=$connection;
$proxy_url=$connection->worker->proxy_url;
write_log(['客戶端連線:開始==】',$connection->client_id]);
$app_list[$client_id] = new AsyncTcpConnection($proxy_url);
$app_list[$client_id]->client_id = $client_id;
$app_list[$client_id]->onMessage = 'app_message';
$app_list[$client_id]->onError = 'app_error';
$app_list[$client_id]->onClose = 'app_close';
$app_list[$client_id]->connect();
write_log(['客戶端連線:完成==】',$connection->client_id]);
catch (Throwable $e) {
write_log(['客戶端連線:異常==】',$connection->client_id,$e->getMessage()]);
}
}
/**
 * 收到訊息處理
 * @param TcpConnection $connection
 * @param $data
 * @return void
 */

functionhandle_message(TcpConnection $connection,$data)void
{
try {
write_log(['收到訊息:',$data]);
global $app_list;
if(TIMEOUT_CLOSE && time()-$connection->lastMessageTime>TIME){
write_log(['收到訊息:超時關閉']);
$connection->close();
return;
}
$app_list[$connection->client_id]->send($data);
$connection->lastMessageTime = time();
write_log(['收到訊息:完']);
catch (Throwable $e) {
write_log(['收到訊息:異常==】',$connection->client_id,$e->getMessage()]);
}
}
/**
 * 處理錯誤
 * @param TcpConnection $connection
 * @return void
 */

functionhandle_error(TcpConnection $connection)void
{
try {
write_log(['處理錯誤:開始==】',$connection->client_id]);
$client_id=$connection->client_id;
global $app_list;
if (empty($app_list[$client_id])) return;
$app_list[$client_id]->close();
write_log(['處理錯誤:完成==】',$client_id]);
catch (Throwable $e) {
write_log(['處理錯誤:異常==】',$e->getMessage()]);
}
}
/**
 * 處理關閉
 * @param TcpConnection $connection
 * @return void
 */

functionhandle_close(TcpConnection $connection)void
{
try {
write_log(['處理關閉:開始==】',$connection->client_id]);
$client_id=$connection->client_id;
global $app_list,$connect_list;
if (empty($app_list[$client_id])) return;
$app_list[$client_id]->close();
unset($connect_list[$client_id]);
write_log(['處理關閉:完成==】',$client_id]);
catch (Throwable $e) {
write_log(['處理關閉:異常==】',$e->getMessage()]);
}
}
$worker = new Worker();
$worker->onWorkerStart = function(){
global $client_list,$proxy_list;
foreach($proxy_list as $k=>$v)
{
$url=$v['type'].'://0.0.0.0:'.$v['local_port'];
$proxy_url=$v['type'].'://'.$v['host'].':'.$v['port'];
echo'監聽地址:'.$url.PHP_EOL;
echo'代理地址:'.$proxy_url.PHP_EOL;
$client_list[$k] = new Worker($url);
$client_list[$k]->proxy_key = $k;
$client_list[$k]->proxy_info = $v;
$client_list[$k]->proxy_url = $proxy_url;
$client_list[$k]->onConnect = 'handle_connection';
$client_list[$k]->onMessage = 'handle_message';
$client_list[$k]->onError = 'handle_error';
$client_list[$k]->onClose = 'handle_close';
$client_list[$k]->listen();
}
};
Worker::runAll();






















啟動

以debug(偵錯)方式啟動

php start.php start

以daemon(守護行程)方式啟動

php start.php start -d

停止

php start.php stop

重新開機

php start.php restart

平滑重新開機

php start.php reload

檢視狀態

php start.php status

Windows 啟動

雙擊 start_for_win.bat