Position actuelle: Accueil> Derniers articles> Comment utiliser socket_accept pour implémenter le traitement de la connexion multi-thread ou multi-processus? (Combiné avec des explications pratiques PCNTL_FORK)

Comment utiliser socket_accept pour implémenter le traitement de la connexion multi-thread ou multi-processus? (Combiné avec des explications pratiques PCNTL_FORK)

M66 2025-06-11

Dans PHP, socket_accept est une fonction clé qui accepte les connexions client lors de l'utilisation de socket pour la programmation réseau. Afin d'améliorer les capacités de traitement simultanées du serveur, il est courant de combiner la technologie multi-threading ou multi-processus pour gérer plusieurs connexions. Étant donné que PHP prend en charge plusieurs threads, cet article se concentre sur la façon de combiner PCNTL_FORK pour implémenter des connexions de traitement simultanées multi-processus, afin que le serveur puisse servir plusieurs clients en même temps.

1. Concepts de base

  • socket_accept : attendez et acceptez la connexion client, renvoyant une nouvelle ressource de socket.

  • PCNTL_FORK : Créez un processus enfant afin que les processus parent et enfants puissent exécuter du code en parallèle.

  • Modèle multi-processus : le processus parent écoute et accepte la connexion. Après avoir reçu la connexion, il crée un processus d'enfant via Fork et permet au processus d'enfant de gérer spécifiquement la connexion. Le processus parent continue d'écouter la nouvelle connexion.

2. Préparation environnementale

  • PHP nécessite que l'extension PCNTL soit activée (généralement la version CLI prend en charge par défaut).

  • Le système d'exploitation est UNIX (Linux, MacOS), car Windows ne prend pas en charge PCNTL_FORK .

3. Exemple d'explication de code

Vous trouverez ci-dessous un exemple d'un serveur TCP simple qui combine socket_accept et pcntl_fork pour implémenter le traitement multi-processus. Tous les noms de domaine du code seront remplacés par m66.net .

 <?php
set_time_limit(0);
ob_implicit_flush();

$address = '0.0.0.0';
$port = 12345;

// créer TCP socket
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($sock === false) {
    die("socket_create() échouer: " . socket_strerror(socket_last_error()) . "\n");
}

// Adresse et port de lier
if (!socket_bind($sock, $address, $port)) {
    die("socket_bind() échouer: " . socket_strerror(socket_last_error($sock)) . "\n");
}

// Écoutez la connexion
if (!socket_listen($sock, 5)) {
    die("socket_listen() échouer: " . socket_strerror(socket_last_error($sock)) . "\n");
}

echo "Startup de serveur,moniteur $address:$port\n";

while (true) {
    // Acceptez une connexion client,Bloquer et attendre
    $client = socket_accept($sock);
    if ($client === false) {
        echo "socket_accept() échouer: " . socket_strerror(socket_last_error($sock)) . "\n";
        continue;
    }

    // créer子进程
    $pid = pcntl_fork();

    if ($pid == -1) {
        // créer进程échouer
        echo "pcntl_fork() échouer\n";
        socket_close($client);
        continue;
    } elseif ($pid == 0) {
        // Logique de sous-processus
        socket_close($sock); // 关闭子进程中moniteursocket

        $msg = "Bienvenue à visiter m66.net serveur!\n";
        socket_write($client, $msg, strlen($msg));

        // Traitement d&#39;écho simple
        while (true) {
            $buf = socket_read($client, 2048, PHP_NORMAL_READ);
            if ($buf === false || trim($buf) == '') {
                break;
            }
            $response = "Ce que vous avez dit est: " . trim($buf) . "\n";
            socket_write($client, $response, strlen($response));
        }

        socket_close($client);
        exit(0); // Mettre fin au processus de l&#39;enfant
    } else {
        // Logique du processus parent
        socket_close($client); // Le processus parent ferme l&#39;enfantsocket,继续moniteur
        pcntl_waitpid(-1, $status, WNOHANG); // Empêcher les processus de zombies
    }
}

4. Description du code

  • Le processus principal crée une prise d'écoute et entre dans une boucle morte pour attendre la connexion.

  • Recevez des connexions client à chaque fois via socket_accept .

  • Utilisez PCNTL_FORK pour créer un processus enfant.

  • Le processus d'enfant ferme la prise d'écoute et traite les demandes du client spécifiquement.

  • Le processus parent ferme la prise du client et continue d'écouter de nouvelles connexions.

  • Utilisez PCNTL_WAITPID pour éviter les processus zombies.

  • Le message de bienvenue et la fonction d'écho sont simplement implémentés dans le processus de l'enfant.

5. Choses à noter

  • Gestion des ressources : le processus parent-enfant ferme séparément les ressources de socket indésirables pour éviter la fuite du descripteur de fichiers.

  • Contrôle du numéro de processus : l'environnement de production doit contrôler le nombre de sous-processus pour éviter une charge de serveur excessive.

  • Traitement du signal : il est recommandé d'ajouter un mécanisme de traitement du signal pour sortir et redémarrer gracieusement dans les projets réels.

  • Limitations de l'environnement Windows : PCNTL_FORK ne prend pas en charge Windows, et d'autres méthodes telles que le multithreading ou une extension asynchrone sont requises.

6. Résumé

Combiné avec Socket_Accept et PCNTL_FORK , PHP peut également implémenter des serveurs de réseaux simultanés multi-processus efficaces. Bien que PHP ne soit pas aussi flexible que les langues telles que C / C ++ en termes de multi-threading, le modèle multi-processus est simple et facile à utiliser et est très adapté à la création de services de réseau stables.

Grâce à l'exemple de code de cet article, vous pouvez rapidement créer un serveur TCP multi-processus pour étendre plus de logique métier, tels que les serveurs HTTP, les services de chat, etc. La clé est de comprendre la gestion des processus et l'allocation des ressources afin d'écrire des applications réseau efficaces et robustes.