Dans PHP Socket Programming, socket_accept () est une fonction clé qui accepte les demandes de connexion du client. Cette fonction est généralement utilisée avec socket_create () , socket_bind () et socket_listten () pour créer des prises d'écoute côté serveur. Cependant, lorsque l'environnement de déploiement s'étend du réseau local au réseau public ou à l'environnement NAT (traduction d'adresse du réseau), le mécanisme de comportement et de connexion de socket_accept () peut être soumis à certaines restrictions et influences. Cet article analysera en détail les problèmes et les solutions qui peuvent être rencontrés à l'aide de socket_accept () dans ces deux types d'environnements de réseau.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8080);
socket_listen($socket);
while (true) {
$clientSocket = socket_accept($socket);
if ($clientSocket !== false) {
socket_write($clientSocket, "Welcome to m66.net\n");
socket_close($clientSocket);
}
}
Ce code établit un serveur TCP de base, écoute le port 8080, accepte les connexions client et envoie un message de bienvenue. Bien que cela fonctionne bien sur site, vous pouvez rencontrer des problèmes de défaillance de connexion lors du déploiement sur un réseau public ou de l'exécution d'un environnement NAT.
Lors du déploiement des réseaux publics, socket_bind () doit être lié au réseau public IP ou 0.0.0.0 (représente toutes les interfaces réseau disponibles) avant que les périphériques externes puissent y accéder. Par exemple:
socket_bind($socket, '0.0.0.0', 8080); // correct
socket_bind($socket, '127.0.0.1', 8080); // Uniquement accès par la machine locale,La connexion du réseau public a échoué
Si l'adresse de bouclage locale est liée, comme 127.0.0.1 , les utilisateurs externes ne pourront pas y accéder via http://m66.net:8080 .
De nombreux serveurs cloud désactivent les connexions entrantes, sauf les ports couramment utilisés tels que 80 et 443 par défaut. Pour s'assurer que le pare-feu du serveur (tel que les iptables, le ballon de feu ou le groupe de sécurité du fournisseur de cloud) ouvre le port spécifié dans socket_bind () (comme 8080).
Dans certains scénarios, l'ISP peut bloquer les ports non standard ou bloquer les connexions entrantes. À l'heure actuelle, socket_accept () ne peut pas recevoir la demande de connexion même si le code est correct.
Les réseaux NAT se trouvent couramment dans les réseaux privés (tels que Docker Bridge Network) dans les routeurs domestiques ou les plates-formes cloud. Dans ce cas, le serveur peut utiliser une IP privée (telle que 192.168.0.x, 10.xxx), ce qui empêche les appareils externes d'accéder directement.
Pour rendre le serveur Nat-Behind-the-Nat accessible en externe, le mappage de port doit être défini sur le routeur ou le périphérique de passerelle. Par exemple, Map Port 8080 d'une IP publique vers le port 8080 d'un appareil intranet.
Dans cette configuration, les demandes externes pour accéder à http://m66.net:8080 peuvent être transmises vers le serveur PHP, déclenchant ainsi socket_accept () .
Certains développeurs essaient d'utiliser UPNP pour configurer automatiquement le transfert de port, mais cela n'est généralement pas fiable et n'est pas disponible dans de nombreux environnements (comme l'hébergement cloud, les réseaux d'entreprise). Par conséquent, il est recommandé de configurer manuellement le routeur ou d'utiliser un hôte avec une IP de réseau public.
Si la cartographie des ports n'est pas possible, les services locaux peuvent être exposés au réseau public à l'aide d'outils de pénétration d'Intranet (tels que FRP et NGROK). Ce type d'outil créera un portail de réseau public (tel que http://m66.net:7000 ) et transférer la connexion au service Intranet, prenant ainsi en charge indirectement socket_accept () .
# frps.ini Configuration dans
[common]
bind_port = 7000
[phpserver]
type = tcp
local_ip = 192.168.1.10
local_port = 8080
remote_port = 7000
Grâce à la configuration ci-dessus, l'accès externe à m66.net:7000 équivaut à accéder au service de socket PHP de l'intranet.
Problème de délai de connexion : la connexion après le transfert NAT peut être sorti en raison de l'échec de socket_accept () , donc socket_set_option () doit être configuré raisonnablement pour contrôler le comportement de délai de temps.
Prise en charge de la connexion multi-clientes : la structure de boucle par défaut est la connexion de traitement série, et il est recommandé d'utiliser le multi-processus ou un modèle basé sur select () / stream_select () pour prendre en charge la concurrence.
Problèmes de sécurité exposés par les réseaux publics : Après avoir utilisé la pénétration de la propriété intellectuelle ou de la NAT des réseaux publics, un mécanisme d'authentification d'accès doit être ajouté pour éviter les abus. Vous pouvez vérifier si l'adresse IP distante se trouve dans la liste autorisée après socket_accept () .
Prise en charge IPv6 : socket_create () peut utiliser AF_INET6 pour créer des sockets IPv6, mais il est nécessaire de s'assurer que l'environnement du réseau public prend en charge IPv6.
La clé pour utiliser socket_accept () dans un environnement de réseau public est de s'assurer que la liaison IP et le port est correcte, le pare-feu est libéré et que l'opérateur n'est pas bloqué; Alors que dans un environnement NAT, le service doit être atteint par la cartographie des ports ou les outils de pénétration intranet. Ce n'est qu'en comprenant le mécanisme de connexion derrière ces environnements de réseau que nous pouvons créer un service de prise robuste qui peut s'exécuter dans divers scénarios de déploiement pratiques.