Position actuelle: Accueil> Derniers articles> Après avoir utilisé socket_export_stream pour convertir des flux, comment éviter les conflits dans les opérations de lecture et d'écriture et d'assurer une utilisation normale des flux?

Après avoir utilisé socket_export_stream pour convertir des flux, comment éviter les conflits dans les opérations de lecture et d'écriture et d'assurer une utilisation normale des flux?

M66 2025-06-22

Dans PHP, socket_export_stream () est une fonction très pratique qui nous permet d'exporter une ressource de socket de bas niveau à une ressource de flux plus avancée basée sur un flux, afin que nous puissions gérer des prises comme nous manipulons des fichiers ou des entrées et sorties standard. Cela simplifie considérablement le processus de développement, en particulier lors de la collaboration avec des API de streaming existantes telles que Stream_Select () , Fread () , FWrite () , etc.

Cependant, après avoir converti des sockets en flux, de nombreux développeurs rencontrent un problème commun: les conflits sont susceptibles de se produire lors de l'exécution des opérations de lecture et d'écriture entrelacées sur le même flux, entraînant des exceptions de données, des blocages ou une perte . Le cœur de ce type de problème réside dans la façon d'organiser raisonnablement le processus de lecture et d'écriture pour assurer la stabilité et la cohérence du flux de données.

Analyse des problèmes

Lorsque vous appelez socket_export_stream () pour convertir Socket en flux, PHP donnera au flux de capacités lisibles et écrit . En théorie, vous pouvez le manipuler directement avec Fread () et FWrite () . Cependant, si les opérations de lecture et d'écriture ne sont pas planifiées, les problèmes suivants peuvent survenir:

  • Écrivez le blocage de l'opération : si l'autre partie ne lit pas de données, appeler fwrite () lorsque le tampon est plein bloquera.

  • Lire le blocage de l'opération : appeler fread () quand il n'y a pas de données de lecture bloqueront.

  • Confusion des données : la synchronisation de lecture et d'écriture simultanée n'est pas effectuée, ce qui entraîne des protocoles incohérents et une défaillance de l'analyse.

Solution

Pour éviter les problèmes ci-dessus, nous pouvons commencer par les aspects suivants pour assurer le flux sûr et efficace pendant l'utilisation:

1. Utilisez stream_set_blocking () pour coopérer avec Stream_Select () pour la planification non bloquante

Définissez le flux sur le mode non bloquant et utilisez Stream_Select () pour déterminer quand lire et écrire pour éviter le blocage.

 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, 'm66.net', 80);
$stream = socket_export_stream($socket);

stream_set_blocking($stream, false); // Définir le mode non bloquant

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

if (stream_select($read, $write, $except, 5)) {
    if (!empty($write)) {
        fwrite($stream, "GET / HTTP/1.1\r\nHost: m66.net\r\n\r\n");
    }

    if (!empty($read)) {
        $response = fread($stream, 8192);
        echo $response;
    }
}

De cette façon, vous ne pouvez contrôler l'écriture que lorsque le flux est écrite et uniquement lorsqu'il est lisible, en évitant le blocage et les déchets de ressources.

2. Split Read and Write Stream Resources (le cas échéant)

Bien que socket_export_stream () renvoie un flux bidirectionnel, dans certains protocoles ou applications, la séparation de la logique de lecture et d'écriture peut réduire les conflits. Vous pouvez séparer les opérations de lecture et d'écriture en appliquant un contrôle du protocole de couche ou en introduisant des coroutines / multiprocesses / threads.

Par exemple, utilisez Stream_Socket_Pair () pour créer deux flux de socket locaux, l'un est responsable de la lecture et l'autre est responsable de l'écriture et construit un canal de transit de données.

3. Ajouter des verrous en lecture et en écrivant ou utilisez un cadre de coroutine à thread unique

Dans les scénarios où Stream_Select () n'est pas utilisé, vous pouvez également ajouter explicitement les verrous dans le programme ou utiliser des frameworks asynchrones (comme Swoole, ReactPHP) pour contrôler l'ordre de lecture et d'écriture.

 $lock = fopen(__FILE__, 'r');
flock($lock, LOCK_EX);

// Écrire des données
fwrite($stream, $data);

// Lire les données après le déverrouillage
flock($lock, LOCK_UN);
$response = fread($stream, 8192);

Bien que cette méthode soit relativement primitive, elle peut efficacement éviter les conflits de ressources simultanés dans les applications scénarisées.

4. Faites attention à la rafraîchissement du tampon et à la commande rapprochée

Lorsque vous utilisez un flux pour terminer l'opération d'écriture, si vous vous attendez à ce que l'autre partie se lise immédiatement, assurez-vous d'appeler fflush () pour actualiser le tampon. Avant de fermer la connexion, vous devez également faire attention à la fermeture de la fin d'écriture, en attendant la lecture de lecture pour terminer la lecture, puis en déconnectant.

 fwrite($stream, $data);
fflush($stream);
fclose($stream);

Résumer

Avec socket_export_stream () , l'opérabilité du flux est améliorée, mais introduit également le défi du contrôle synchrone. Pour éviter les conflits de lecture et d'écriture, vous pouvez:

  • Utilisez Stream_Select () pour planifier avec précision;

  • Utilisé en conjonction avec le mode non bloquant;

  • Introduire des serrures, des coroutines ou des mécanismes de traitement asynchrones;

  • Gérez le tampon actualiser et fermer les horaires.

Grâce à ces méthodes, la fiabilité et la maintenabilité des flux de conversion de socket dans la programmation du réseau PHP peuvent être efficacement améliorées.