-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathtcp-proxy.php
118 lines (108 loc) · 3.66 KB
/
tcp-proxy.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php
class ProxyServer
{
protected $frontends;
protected $backends;
/**
* @var swoole_server
*/
protected $serv;
protected $index = 0;
protected $mode = SWOOLE_BASE;
protected $backendServer = array('host' => '127.0.0.1', 'port' => '80');
function run()
{
$serv = new swoole_server("127.0.0.1", 9509, $this->mode);
$serv->set(array(
'worker_num' => 8, //worker process num
//'backlog' => 128, //listen backlog
//'open_tcp_keepalive' => 1,
//'log_file' => '/tmp/swoole.log', //swoole error log
));
$serv->on('WorkerStart', array($this, 'onStart'));
$serv->on('Receive', array($this, 'onReceive'));
$serv->on('Close', array($this, 'onClose'));
$serv->on('WorkerStop', array($this, 'onShutdown'));
$serv->start();
}
function onStart($serv)
{
$this->serv = $serv;
echo "Server: start.Swoole version is [" . SWOOLE_VERSION . "]\n";
}
function onShutdown($serv)
{
echo "Server: onShutdown\n";
}
function onClose($serv, $fd, $from_id)
{
//清理掉后端连接
if (isset($this->frontends[$fd]))
{
$backend_socket = $this->frontends[$fd];
$backend_socket->closing = true;
$backend_socket->close();
unset($this->backends[$backend_socket->sock]);
unset($this->frontends[$fd]);
}
echo "onClose: frontend[$fd]\n";
}
function onReceive($serv, $fd, $from_id, $data)
{
//尚未建立连接
if (!isset($this->frontends[$fd]))
{
//连接到后台服务器
$socket = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$socket->closing = false;
$socket->on('connect', function (swoole_client $socket) use ($data)
{
$socket->send($data);
});
$socket->on('error', function (swoole_client $socket) use ($fd)
{
echo "ERROR: connect to backend server failed\n";
$this->serv->send($fd, "backend server not connected. please try reconnect.");
$this->serv->close($fd);
});
$socket->on('close', function (swoole_client $socket) use ($fd)
{
echo "onClose: backend[{$socket->sock}]\n";
unset($this->backends[$socket->sock]);
unset($this->frontends[$fd]);
if (!$socket->closing)
{
$this->serv->close($fd);
}
});
$socket->on('receive', function (swoole_client $socket, $_data) use ($fd)
{
//PHP-5.4以下版本可能不支持此写法,匿名函数不能调用$this
//可以修改为类静态变量
$this->serv->send($fd, $_data);
});
if ($socket->connect($this->backendServer['host'], $this->backendServer['port']))
{
$this->backends[$socket->sock] = $fd;
$this->frontends[$fd] = $socket;
}
else
{
echo "ERROR: cannot connect to backend server.\n";
$this->serv->send($fd, "backend server not connected. please try reconnect.");
$this->serv->close($fd);
}
}
//已经有连接,可以直接发送数据
else
{
/**
* @var $socket swoole_client
*/
$socket = $this->frontends[$fd];
$socket->send($data);
}
}
}
$serv = new ProxyServer();
$serv->run();