Position actuelle: Accueil> Derniers articles> socket_accept () coincé? Explication détaillée des différences entre les modes de blocage et de non-blocage

socket_accept () coincé? Explication détaillée des différences entre les modes de blocage et de non-blocage

M66 2025-05-20

Lorsque vous utilisez PHP pour la programmation réseau, de nombreux développeurs rencontrent souvent un problème lors de l'utilisation de socket_accept () pour créer un serveur TCP: le programme est bloqué et ne peut pas continuer à exécuter. Ce phénomène découle principalement d'une compréhension insuffisante du "mode de blocage" et du "mode non bloquant". Cet article expliquera pourquoi socket_accept () "coincé" et expliquer en détail la différence entre les modes de blocage et de non-blocage.

1. Qu'est-ce que socket_accept () ?

socket_accept () est une fonction dans l'extension de socket PHP qui accepte les demandes de connexion des clients. Après avoir créé une prise avec socket_create () et utilisé socket_bind () et socket_listten () pour commencer à écouter, vous devez utiliser socket_accept () pour recevoir la connexion:

 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8080);
socket_listen($socket);

while (true) {
    $client = socket_accept($socket);
    // droite $client Effectuer des opérations de lecture et d'écriture
}

Dans l'exemple ci-dessus, socket_accept () continuera de bloquer en attendant la connexion jusqu'à ce qu'un client se connecte.

2. Pourquoi est-ce "coincé"?

Le soi-disant "coincé" est en fait le programme attend la connexion mais ne revient pas. Ce n'est pas un bug, mais un comportement normal en mode de blocage.

Par défaut, PHP Socket est en mode de blocage. Cela signifie:

  • Si aucun client n'est connecté au serveur, socket_accept () attendra;

  • Le CPU n'exécutera pas le code suivant jusqu'à ce que socket_accept () renvoie le résultat.

Ainsi, lorsque vous déboguez ou exécutez le serveur, sans connexion client, le programme sera toujours "coincé" dans la ligne socket_accept () .

Ceci est acceptable dans les environnements de production, car le serveur doit simplement attendre la connexion. Mais dans les environnements où le débogage ou plusieurs tâches doivent être gérés, ce comportement de blocage peut devenir un problème.

3. Solutions pour le mode non bloquant

Si vous souhaitez que le programme continue de s'exécuter sans connexion, comme effectuer certaines opérations régulièrement ou détecter d'autres événements, vous devez utiliser le mode non bloquant .

Définir le mode non bloquant:

 socket_set_nonblock($socket);

À l'heure actuelle, socket_accept () n'attendra plus, mais à la place:

  • Retourner au socket client lorsqu'il y a une connexion;

  • Renvoie false immédiatement lorsqu'il n'y a pas de connexion et définissez le code d'erreur sur socket_eagain ou socket_ewouldblock .

Exemple de code:

 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8080);
socket_listen($socket);
socket_set_nonblock($socket);

while (true) {
    $client = @socket_accept($socket);
    if ($client === false) {
        // Pas de connexion,Continuez à faire d'autres choses
        echo "En attente de connexion...\n";
        sleep(1);
    } else {
        // A reçu la connexion avec succès
        socket_write($client, "Hello from m66.net\n");
        socket_close($client);
    }
}

4. Utilisez socket_select () pour gérer le blocage plus gracieusement

Une autre pratique courante consiste à utiliser socket_select () pour détecter s'il y a des prises qui peuvent être lues et écrites, ce qui peut éviter la vérification de la boucle aveugle:

 $read = [$socket];
$write = $except = null;

if (socket_select($read, $write, $except, 5) > 0) {
    $client = socket_accept($socket);
    // Gérer les connexions du client
}

Cette méthode ne bloque pas indéfiniment car vous pouvez définir l'heure du délai d'expiration. Il convient également aux scènes où plusieurs prises sont écoutées en même temps et est une technique courante dans la programmation réseau haute performance.

5. Résumé

  • socket_accept () bloque par défaut, et s'il n'y a pas de demande de connexion, il attendra;

  • Le comportement de blocage n'est pas un bug, mais cela entraînera la "stagner" du programme en attendant la connexion;

  • Vous pouvez définir socket_set_nonblock () en mode non bloquant pour éviter la stagnation du programme;

  • Une solution plus avancée consiste à utiliser socket_select () pour gérer l'état de plusieurs prises.