对swoole理解不深,不知道怎么处理socket shutdown只关闭读/写这样,还有就是连接超时,读写超时这种怎么处理。在网上看到作者说要用定时器,感觉好麻烦,所以,这次的代理,虽然个人用,一般不会有什么问题,但离产品级的代理,还有段路要走。
如果要利用多核,就使用process模式,设置worker个数为cpu数量即可。
set([ 'max_conn' => 1000, 'daemonize' => 1, 'reactor_num' => 1, 'worker_num' => 1, 'dispatch_mode' => 2, 'buffer_output_size' => 128 * 1024 * 1024, 'open_cpu_affinity' => 1, 'open_tcp_nodelay' => 1, 'log_file' => 'socks5_server.log', ]); $server->on('connect', [$this, 'onconnect']); $server->on('receive', [$this, 'onreceive']); $server->on('close', [$this, 'onclose']); $server->start(); } public function onconnect($server, $fd, $fromid) { $this->clients[$fd] = new client(); } public function onreceive($server, $fd, $fromid, $data) { ($this->clients[$fd])->data .= $data; $this->parse($server, $fd); } public function onclose($server, $fd, $fromid) { $client = $this->clients[$fd]; $client->connected = false; } private function parse($server, $fd) { $client = $this->clients[$fd]; switch ($client->status) { case 0: { if (strlen($client->data) >= 2) { $request = unpack('c*', substr($client->data, 0, 2)); if ($request[1] !== 0x05) { echo '协议不正确:' . $request[1], php_eol; $server->close($fd); break; } $nmethods = $request[2]; if (strlen($client->data) >= 2 + $nmethods) { $client->data = substr($client->data, 2 + $nmethods); $server->send($fd, \x05\x00); $client->status = 1; } } } case 1: { if (strlen($client->data) data); $atype = $request[4]; if ($atype === 0x03) { // domain $domainlen = $request[5]; if (strlen($client->data) data, 5, $domainlen); $port = unpack('n', substr($client->data, 5 + $domainlen, 2))[1]; $client->data = substr($client->data, 5 + $domainlen + 2); } else if ($atype === 0x01) { // ipv4 $domain = long2ip(unpack('n', substr($client->data, 4, 4))[1]); $port = unpack('n', substr($client->data, 8, 2))[1]; $client->data = substr($client->data, 10); } else { echo '不支持的atype:' . $atype, php_eol; $server->close($fd); break; } $remote = new swoole_client(swoole_sock_tcp, swoole_sock_async); $remote->on('connect', function($cli) use($client, $server, $fd, $remote) { $server->send($fd, \x05\x00\x00\x01\x00\x00\x00\x00\x00\x00); $client->status = 2; $client->remote = $remote; }); $remote->on(error, function(swoole_client $cli) use($server, $fd) { //$server->send($fd, ); // todo 连接不上remote echo 'connect to remote error.', php_eol; $server->close($fd); }); $remote->on('receive', function($cli, $data) use($server, $fd, $client) { if (!$client->connected) { echo 'connection has been closed.', php_eol; return; } $server->send($fd, $data); }); $remote->on('close', function($cli) use($server, $fd, $client) { $client->remote = null; }); if ($atype === 0x03) { swoole_async_dns_lookup($domain, function($host, $ip) use($remote, $port, $server, $fd) { //todo 当host为空时的处理。貌似不存在的域名都解析成了本机的外网ip,奇怪 if (empty($ip) || empty($host)) { echo host:{$host}, ip:{$ip}\n; $server->close($fd); return; } $remote->connect($ip, $port); }); } else { $remote->connect($domain, $port); } } case 2: { if (strlen($client->data) === 0) { break; } if ($client->remote === null) { echo 'remote connection has been closed.', php_eol; break; } $sendbytecount = $client->remote->send($client->data); if ($sendbytecount === false || $sendbytecount data)) { echo 'data length:' , strlen($client->data), ' send byte count:', $sendbytecount, php_eol; echo $client->data, php_eol; $server->close($fd); } $client->data = ''; } } }}(new server())->start();
以上就介绍了100多行php代码实现socks5代理服务器[2],包括了socks5代理服务器方面的内容,希望对php教程有兴趣的朋友有所帮助。
