Aktueller Standort: Startseite> Neueste Artikel> Wie kann man mit Socket_Recv mit Socket_Select einen nicht blockierenden Empfang erreichen? Beigefügter Code

Wie kann man mit Socket_Recv mit Socket_Select einen nicht blockierenden Empfang erreichen? Beigefügter Code

M66 2025-06-22

In PHP sind Socket_Recv und Socket_Select -Funktionen sehr häufige Tools bei der Netzwerkprogrammierung, insbesondere wenn Sie nicht blockierende E/A-Operationen ausführen müssen. Mit diesen beiden Funktionen können Sie eine Blockade vermeiden, die durch das Warten auf Netzwerkdaten verursacht wird, wodurch die Effizienz und Reaktionsfähigkeit Ihres Programms verbessert wird. In diesem Artikel wird ausführlich vorgestellt, wie diese beiden Funktionen verwendet werden, um den nicht blockierenden Empfang zu erreichen.

1. Was ist nicht blockierender Empfang?

Wenn Sie im traditionellen Blockierungsempfang Socket_Recv und andere Funktionen verwenden, um Daten zu empfangen, wird das Programm in dieser Codezeile angehalten und wird nicht weiter ausgeführt, bis Daten eintreffen oder ein Timeout erfolgen. Dies bedeutet, dass das Programm "festgefahren" und keine anderen Operationen ausgeführt werden können, wenn keine Daten eintrafen.

Anstatt den Empfang zu blockieren, bedeutet dies, dass das Programm nicht aufhört, auf Daten zu warten. Es wird beim Empfangen von Daten prüfen. Wenn es keine Daten gibt, können andere Vorgänge fortgesetzt werden. Auf diese Weise wird das Programm nicht blockiert, während Sie auf Daten warten, während Sie E/A -Operationen ausführen.

2. Verwenden Sie Socket_Select -Funktion

Die Funktion Socket_Select bietet eine Möglichkeit, zu überprüfen, ob mehrere Sockets fertig sind. Dadurch können wir das Blockieren des Wartens vermeiden. Wenn wir Socket_Select anrufen, wird prüfen, ob der angegebene Socket Daten zum Lesen enthält. In diesem Fall wird das entsprechende Socket -Objekt zurückgegeben. Sie können diese Funktion verwenden, um nicht blockierende Empfangsoperationen auf mehreren Sockeln durchzuführen.

Grundlegende Syntax von Socket_Select :

 <span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-title function_ invoke__">socket_select</span></span><span> ( </span><span><span class="hljs-keyword">array</span></span><span> &amp;</span><span><span class="hljs-variable">$read</span></span><span>, </span><span><span class="hljs-keyword">array</span></span><span> &amp;</span><span><span class="hljs-variable">$write</span></span><span>, </span><span><span class="hljs-keyword">array</span></span><span> &amp;</span><span><span class="hljs-variable">$except</span></span><span>, </span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$tv_sec</span></span><span>, </span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$tv_usec</span></span><span> )
</span></span>
  • $ Read : Ein Array mit allen Sockeln, die als lesbar erkannt werden müssen.

  • $ write : Ein Array mit allen Sockeln, die als beschreibbar erkannt werden müssen.

  • $ außer : ein Array mit allen Sockeln, die für Ausnahmen erkannt werden müssen.

  • $ TV_SEC und $ TV_USEC : Gibt die Zeitüberschreitung (Sekunden und Mikrosekunden) an. Wenn es auf Null gesetzt ist, ist es unendlich, dass es unendlich wartet.

Grundlegende Syntax von Socket_RECV :

 <span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-title function_ invoke__">socket_recv</span></span><span> ( resource </span><span><span class="hljs-variable">$socket</span></span><span> , </span><span><span class="hljs-keyword">string</span></span><span> &amp;</span><span><span class="hljs-variable">$buf</span></span><span> , </span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$length</span></span><span> , </span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$flags</span></span><span> )
</span></span>
  • $ Socket : Die Socket -Ressource zum Empfangen von Daten.

  • $ buf : Die empfangenen Daten werden in dieser Variablen gespeichert.

  • $ Länge : Die maximale Anzahl von Bytes zu erhalten.

  • $ flags : Flags, die den Empfangsvorgang steuern, normalerweise 0.

3. Beispielcode

Hier ist ein vollständiges Beispiel für die Verwendung von Socket_Recv mit Socket_Select , um den nicht blockierenden Empfang zu erreichen:

 <span><span><span class="hljs-meta">&lt;?php</span></span><span>
</span><span><span class="hljs-comment">// Erstellen a TCP socket</span></span><span>
</span><span><span class="hljs-variable">$server</span></span><span> = </span><span><span class="hljs-title function_ invoke__">socket_create</span></span><span>(AF_INET, SOCK_STREAM, SOL_TCP);

</span><span><span class="hljs-comment">// Einrichten des Serveradresses und des Ports</span></span><span>
</span><span><span class="hljs-variable">$address</span></span><span> = </span><span><span class="hljs-string">'127.0.0.1'</span></span><span>;
</span><span><span class="hljs-variable">$port</span></span><span> = </span><span><span class="hljs-number">12345</span></span><span>;

</span><span><span class="hljs-comment">// Binden socket</span></span><span>
</span><span><span class="hljs-title function_ invoke__">socket_bind</span></span><span>(</span><span><span class="hljs-variable">$server</span></span><span>, </span><span><span class="hljs-variable">$address</span></span><span>, </span><span><span class="hljs-variable">$port</span></span><span>);

</span><span><span class="hljs-comment">// Beginnen Sie mit der Überwachung</span></span><span>
</span><span><span class="hljs-title function_ invoke__">socket_listen</span></span><span>(</span><span><span class="hljs-variable">$server</span></span><span>);

</span><span><span class="hljs-comment">// Timeout einstellen</span></span><span>
</span><span><span class="hljs-variable">$timeout</span></span><span> = </span><span><span class="hljs-number">10</span></span><span>;  </span><span><span class="hljs-comment">// Auszeit 10 Zweite</span></span><span>
</span><span><span class="hljs-variable">$read</span></span><span> = [</span><span><span class="hljs-variable">$server</span></span><span>];  </span><span><span class="hljs-comment">// Wird verwendet, um festzustellen, ob eine Verbindung besteht</span></span><span>
</span><span><span class="hljs-variable">$write</span></span><span> = </span><span><span class="hljs-variable">$except</span></span><span> = [];

</span><span><span class="hljs-comment">// Geben Sie die Schleife ein,Warten auf die Kundenverbindung</span></span><span>
</span><span><span class="hljs-keyword">while</span></span><span> (</span><span><span class="hljs-literal">true</span></span><span>) {
    </span><span><span class="hljs-comment">// verwenden socket_select Um festzustellen, ob es eine neue Verbindung gibt</span></span><span>
    </span><span><span class="hljs-variable">$changed</span></span><span> = </span><span><span class="hljs-title function_ invoke__">socket_select</span></span><span>(</span><span><span class="hljs-variable">$read</span></span><span>, </span><span><span class="hljs-variable">$write</span></span><span>, </span><span><span class="hljs-variable">$except</span></span><span>, </span><span><span class="hljs-variable">$timeout</span></span><span>);

    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$changed</span></span><span> === </span><span><span class="hljs-literal">false</span></span><span>) {
        </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"socket_select failed\n"</span></span><span>;
        </span><span><span class="hljs-keyword">break</span></span><span>;
    }

    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$changed</span></span><span> &gt; </span><span><span class="hljs-number">0</span></span><span>) {
        </span><span><span class="hljs-comment">// Überprüfen Sie, ob eine neue Client -Verbindung vorhanden ist</span></span><span>
        </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">in_array</span></span><span>(</span><span><span class="hljs-variable">$server</span></span><span>, </span><span><span class="hljs-variable">$read</span></span><span>)) {
            </span><span><span class="hljs-variable">$client</span></span><span> = </span><span><span class="hljs-title function_ invoke__">socket_accept</span></span><span>(</span><span><span class="hljs-variable">$server</span></span><span>);
            </span><span><span class="hljs-variable">$read</span></span><span>[] = </span><span><span class="hljs-variable">$client</span></span><span>;  </span><span><span class="hljs-comment">// Neue Verbindungen werden hinzugefügt, um das Array zu lesen</span></span><span>
            </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Client connected\n"</span></span><span>;
        }

        </span><span><span class="hljs-comment">// Durch alle angeschlossenen wiederholen socket,Überprüfen Sie, ob Daten zu lesen sind</span></span><span>
        </span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$read</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$sock</span></span><span>) {
            </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$sock</span></span><span> !== </span><span><span class="hljs-variable">$server</span></span><span>) {
                </span><span><span class="hljs-variable">$data</span></span><span> = </span><span><span class="hljs-string">''</span></span><span>;
                </span><span><span class="hljs-variable">$bytes_received</span></span><span> = </span><span><span class="hljs-title function_ invoke__">socket_recv</span></span><span>(</span><span><span class="hljs-variable">$sock</span></span><span>, </span><span><span class="hljs-variable">$data</span></span><span>, </span><span><span class="hljs-number">1024</span></span><span>, MSG_DONTWAIT);
                </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$bytes_received</span></span><span> === </span><span><span class="hljs-number">0</span></span><span>) {
                    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Client disconnected\n"</span></span><span>;
                    </span><span><span class="hljs-title function_ invoke__">socket_close</span></span><span>(</span><span><span class="hljs-variable">$sock</span></span><span>);
                    </span><span><span class="hljs-variable">$read</span></span><span> = </span><span><span class="hljs-title function_ invoke__">array_diff</span></span><span>(</span><span><span class="hljs-variable">$read</span></span><span>, [</span><span><span class="hljs-variable">$sock</span></span><span>]);  </span><span><span class="hljs-comment">// Entfernen Sie dies aus der Leseliste socket</span></span><span>
                } </span><span><span class="hljs-keyword">elseif</span></span><span> (</span><span><span class="hljs-variable">$bytes_received</span></span><span> &gt; </span><span><span class="hljs-number">0</span></span><span>) {
                    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Received data: <span class="hljs-subst">$data</span></span></span><span>\n";
                }
            }
        }
    }

    </span><span><span class="hljs-comment">// Hier kann hier mehr Verarbeitungslogik hinzugefügt werden,Überprüfen Sie beispielsweise Schreibvorgänge、Auszeit处理等</span></span><span>
}

</span><span><span class="hljs-title function_ invoke__">socket_close</span></span><span>(</span><span><span class="hljs-variable">$server</span></span><span>);
</span><span><span class="hljs-meta">?&gt;</span></span><span>
</span></span>

Code -Interpretation:

  1. Socket erstellen und binden : Erstellen Sie eine TCP -Socket mit Socket_Create und binden Sie sie mit Socket_Bind an die angegebene Adresse und den Port.

  2. Socket_Select hört auf mehrere Sockets zu : Das in Socket_Select angehörte $ Read -Array, und mit dem $ Server -Socket wird neue Client -Verbindungen akzeptiert. Der $ Timeout -Parameter wird auf 10 Sekunden gesetzt, dh innerhalb von 10 Sekunden kehrt Socket_Select zurück, wenn keine Daten in oder eine neue Verbindung übergeben werden.

  3. Empfangen Sie Daten : Wenn Daten gelesen werden müssen, wird die nicht blockierende Rezeption über Socket_RECV durchgeführt. Wenn der Client abtrennt, schließen Sie den entsprechenden Socket und entfernen Sie ihn aus dem $ Read -Array.

4.. Dinge zu beachten

  • Nicht blockierender Modus : In diesem Fall haben wir das MSG_Dontwait -Flag verwendet, um den nicht blockierenden Empfang zu erreichen, was bedeutet, dass Socket_Recv das Programm nicht blockiert, wenn keine Daten gelesen werden.

  • Verwendung von Socket_Select : Socket_Select wird verwendet, um den Status mehrerer Steckdosen zu überprüfen. Im nicht blockierenden Modus können Sie vermeiden, dass Sie ständig auf Daten aus einem Socket warten, können jedoch sofort verarbeitet werden, wenn Daten verfügbar sind.

  • Speicherverwaltung : Wenn Sie Socket_Select verwenden, entfernen Sie unbedingt geschlossene Sockets aus dem $ Read -Array, um Speicherlecks und ungültige Socket -Erkennung zu vermeiden.

5. Zusammenfassung

Durch die Kombination von Socket_Recv und Socket_Select können Sie den nicht blockierenden Empfang sehr bequem erreichen. Diese Methode verhindert nicht nur, dass Programme aufgrund des Wartens auf Daten blockieren, sondern kann auch mehrere Socket -Verbindungen effizient verarbeiten und eine effizientere Netzwerkkommunikation erreichen.

Die nicht blockierende Rezeption ist eine wichtige Technologie, die besonders nützlich ist, wenn sie mit geringer Latenz-Netzwerkdienste mit hoher Konsequenz aufbauen. Durch die flexible Verwendung der PHP -Socket -Programmierung können die Leistung und Skalierbarkeit von Anwendungen verbessert werden.