100 lines of code can (simple) realize what fun? This article shows an example of 100 lines of PHP code simple implementation of SOCKS5 Proxy Server module, we hope to help.
Well, the following is the proxy that is implemented using the thread pool, which, according to reason, exits when the pool is shutdown (), Listen to socket also want to shutdown, but hundred lines of code, will not reluctantly, with CTRL + C, let the operating system to reclaim resources.
php is not good at network programming in the embodiment of where? First I use STREAM_SOCKET_XXX-related functions, why not use the socket extension? Because of a problem with the socket extension. and Stream_set_timeout to stream_socket_recvfrom these advanced operations, does not work. And that's what you need to think about when you write an agent. For example, when connecting to a remote target server, there is no time-out control and it is easy to run full of thread pools.
test, use curl, right, only remote DNS resolution is currently supported, why? Because this toy later but to achieve WO learn to surf the Internet yo: Curl--socks5-hostname 127.0.0.1:1080 http://ip.cn
Class Pipe extends threaded{private $client; Private $remote; Public function __construct ($client, $remote) {$this->client = $client; $this->remote = $remote; } public Function run () {for (;;) {$data = Stream_socket_recvfrom ($this->client, 4096); if ($data = = = False | | strlen ($data) = = = 0) {break; } $sendBytes = Stream_socket_sendto ($this->remote, $data); if ($sendBytes <= 0) {break; }} stream_socket_shutdown ($this->client, STREAM_SHUT_RD); Stream_socket_shutdown ($this->remote, STREAM_SHUT_WR); }}class Client extends threaded{public $fd; Public function __construct ($FD) {$this->fd = $FD; Public Function Run () {$data = Stream_socket_recvfrom ($this->fd, 2); $data = Unpack (' c* ', $data); if ($data [1]!== 0x05) {stream_socket_shutdown ($this->fd, stream_shut_rdwr); Echo ' protocol is not correct. ', Php_eol; Return } $nmethods = $data [2]; $data = Stream_socket_recvfrom ($this->fd, $nmethods); Stream_socket_sendto ($this->fd, "\x05\x00"); $data = Stream_socket_recvfrom ($this->fd, 4); $data = Unpack (' c* ', $data); $addressType = $data [4]; if ($addressType = = = 0x03) {//Domain $domainLength = unpack (' C ', Stream_socket_recvfrom ($this->fd, 1)) [1]; $data = Stream_socket_recvfrom ($this->fd, $domainLength + 2); $domain = substr ($data, 0, $domainLength); $port = Unpack ("n", substr ($data,-2)) [1]; } else {Stream_socket_shutdown ($this->fd, stream_shut_rdwr); Echo ' Please use remote DNS resolution. ', Php_eol; } stream_socket_sendto ($this->fd, "\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00"); echo "{$domain}:{$port}", Php_eol; $remote = Stream_socket_client ("tcp://{$domain}:{$port}"); if ($remote = = = False) {Stream_socket_shutdown ($this->fd, stream_shut_rdwr); Return } $pool = $this->worker->pipepool; $pipe 1 = new Pipe ($remote, $this->fd); $pipe 2 = new Pipe ($this->fd, $remote); $pool->submit ($pipe 1); $pool->submit ($pipe 2); }}class Proxyworker extends worker{public $pipePool; Public function __construct ($pipePool) {$this->pipepool = $pipePool; }} $server = Stream_socket_server (' tcp://0.0.0.0:1080 ', $errno, $errstr), if ($server = = = False) exit ($ERRSTR); $pipePool = new Pool (worker::class), $pool = new Pool (' Proxyworker ', [$pipePool]); for (;;) {$fd = @stream_socket_accept ($server, 60); if ($fd = = = False) continue; $pool->submit (New Client ($FD));}
related recommendations:
php using Swoole to update client data in real time
windows?
php Learn Curl's reptile instance