100行PHP代码实现socks5代理服务器
前两天在B站上看到一个小伙纸100元组装个电脑打LOL画质流畅,突发奇想100行代码能(简单)实现个啥好玩的。我主要是做php开发的,于是就有了本文。
当然,由于php(不算swoole扩展)本身不擅长做网络服务端编程,所以这个代理,只是个玩具,离日常使用有点距离。如果想使用稳定可靠的加密(所以能禾斗学上网)代理,可以用这个:https://github.com/momaer/asocks-go也是100来行代码使用go实现。
写的过程中发现php多线程还是难的。比如我开始想每个连接新建一个线程。但这个线程得保存起来(比如保存到数组),比如官方例子中的这个:https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php 要放到$clients这个数组里,不然,你试试(curl -L一个要301的地址)就知道出现什么情况了。
这个例子说了in the real world, do something here to ensure clients not running are destroyed 但是,如何把不再运行的连接销毁却没有讲。恩。我试了把$clients放到一个类里,把类传给线程类,然后在线程类要结束时把$clients里对应的连接给unset掉,无果。
那,以下就是使用线程池来实现的代理,按道理讲,退出时池要shutdown(),监听socket也要shutdown的,但百行代码,就不勉强了,随着ctrl + c,就让操作系统来回收资源吧。
php不擅长网络编程体现在哪里呢?首先我用的是stream_socket_XXX相关的函数,为啥不用socket扩展呢?因为socket扩展有问题,参见:https://github.com/krakjoe/pthreads/issues/581 而stream_set_timeout对stream_socket_recvfrom这些高级操作,不起作用,参见:http://php.net/manual/en/function.stream-set-timeout.php 而这些,在写代理时都需要考虑的。比如连接远程目标服务器时,没有超时控制,很容易就线程池跑满了。
测试的话,使用curl即可,对了,目前只支持远程dns解析,为啥呢?因为这个玩具后期可是要实现禾斗学上网的哟: 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 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 '协议不正确.', 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 '请使用远程dns解析.', 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; $pipe1 = new Pipe($remote, $this->fd); $pipe2 = new Pipe($this->fd, $remote); $pool->submit($pipe1); $pool->submit($pipe2); } } 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(200, Worker::class); $pool = new Pool(50, 'ProxyWorker', [$pipePool]); for( ; ; ) { $fd = @stream_socket_accept($server, 60); if ($fd === false) continue; $pool->submit(new Client($fd)); }
以上就介绍了100行PHP代码实现socks5代理服务器,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds











Cet article vous apporte des connaissances pertinentes sur php+socket, qui présente principalement le multiplexage IO et comment php+socket implémente le serveur Web ? Les amis intéressés peuvent jeter un œil ci-dessous. J'espère que cela sera utile à tout le monde.

1. Programmation de socket basée sur le protocole TCP 1. Le flux de travail du socket commence par le côté serveur. Le serveur initialise d'abord le Socket, puis se lie au port, écoute le port, appelle accepter pour bloquer et attend que le client se connecte. A ce moment, si un client initialise un Socket puis se connecte au serveur (connect), si la connexion réussit, la connexion entre le client et le serveur est établie. Le client envoie une demande de données, le serveur reçoit la demande et traite la demande, puis envoie les données de réponse au client, le client lit les données et ferme enfin la connexion. Utilisez le code Python suivant pour l'implémenter. : importations

La première étape du côté de SpringBoot consiste à introduire les dépendances. Nous devons d'abord introduire les dépendances requises pour WebSocket, ainsi que les dépendances pour le traitement du format de sortie com.alibabafastjson1.2.73org.springframework.bootspring-boot-starter-websocket. La deuxième étape consiste à créer la classe de configuration WebSocket importorg springframework.context.annotation.Bean;importorg.springframework.context.annotation.Config.

Le fonctionnement du flux est un point fort de Java8 ! Bien que java.util.stream soit très puissant, de nombreux développeurs l'utilisent encore rarement dans leur travail réel. L'une des raisons les plus critiquées est qu'il est difficile à déboguer. C'était effectivement le cas au début, à cause des opérations de streaming. car le flux ne peut pas être utilisé dans DEBUG Lorsqu'il s'agit d'une ligne de code, lorsqu'il s'agit de l'étape suivante, de nombreuses opérations sont en fait passées en même temps, il nous est donc difficile de juger quelle ligne pose problème. Plug-in : JavaStreamDebugger Si la version d'IDEA que vous utilisez est relativement nouvelle, ce plug-in est déjà inclus et n'a pas besoin d'être installé. S'il n'est pas encore installé, installez-le manuellement, puis continuez ci-dessous.

PHP est un langage de développement couramment utilisé qui peut être utilisé pour développer diverses applications Web. En plus des requêtes et réponses HTTP courantes, PHP prend également en charge la communication réseau via Sockets pour obtenir une interaction de données plus flexible et plus efficace. Cet article présentera les méthodes et techniques d'implémentation de la communication Socket en PHP et joindra des exemples de code spécifiques. Qu'est-ce que Socket Communication Socket est une méthode de communication dans un réseau qui peut transférer des données entre différents ordinateurs. par S

Problèmes courants de communication réseau et de sécurité et solutions en C# À l'ère d'Internet d'aujourd'hui, la communication réseau est devenue un élément indispensable du développement logiciel. En C#, nous rencontrons généralement certains problèmes de communication réseau, tels que la sécurité de la transmission des données, la stabilité de la connexion réseau, etc. Cet article abordera en détail les problèmes courants de communication réseau et de sécurité en C# et fournira les solutions correspondantes et des exemples de code. 1. Problèmes de communication réseau Interruption de la connexion réseau : pendant le processus de communication réseau, la connexion réseau peut être interrompue, ce qui peut entraîner

Cet article vous apporte des connaissances pertinentes sur php+socket. Il présente principalement qu'est-ce que socket ? Comment php+socket réalise-t-il la transmission de données client-serveur ? Les amis intéressés peuvent jeter un œil ci-dessous. J'espère que cela sera utile à tout le monde.

Le flux de java8 prend maxpublicstaticvoidmain(String[]args){Listlist=Arrays.asList(1,2,3,4,5,6);Integermax=list.stream().max((a,b)->{if ( a>b){return1;}elsereturn-1;}).get();System.out.println(max);}Remarque : la taille est déterminée ici par des nombres positifs et négatifs et des valeurs 0. Au lieu de l'écrire directement if(a>b){returna;}elseretur
