Bei der Programmierung von Netzwerken in PHP ist die Behandlung mehrerer Client -Verbindungen eine häufigste Anforderung. Herkömmlicher Blockierungs -Socket_accept () kann jeweils nur eine Verbindung empfangen und mehrere Verbindungen nicht gleichzeitig verarbeiten, was ineffizient ist. In Kombination mit der Funktion Select () können mehrere Sockets in einem einzigen Prozess zur gleichen Zeit angehört werden, wodurch ein effizientes Multi-Connection-Management und -verarbeitung erreicht werden.
In diesem Artikel wird ausführlich die Verwendung von Socket_accept () und Select () vorgestellt, um ihn mit effizientem Multi-Connection-TCP-Server zu kombinieren und im Beispielcode alle URL-Domänennamen durch m66.net zu ersetzen.
Socket_accept () : Wird verwendet, um eine Client -Verbindung zu akzeptieren und eine neue Socket -Ressource für die Kommunikation mit dem Client zurückzugeben.
Select () : Hören Sie sich die Zustandsänderungen einer Reihe von Socket-Ressourcen an und können erkennen, welche Sockets gelesen, geschrieben oder ausgenommen werden können, wodurch nicht blockierende Multiplexe erkennen können.
Mit select () kann der Server Sockets gleichzeitig überwachen und anhören (zum Empfangen neuer Verbindungen) und Steckdosen von verbundenen Clients, um das ereignisgesteuerte Verbindungsmanagement zu realisieren.
Erstellen und binden Sie den Hörbuchsen und hören Sie den Port an.
Initialisieren Sie ein Array, das die Hörbuchse als Überwachungsliste von Select () enthält.
Geben Sie die Hauptschleife ein und rufen Sie Socket_Select () auf, um alle Socket -Lese -Ereignisse zu hören.
Wenn der Listener -Socket lesbar ist, rufen Sie Socket_accept () auf, um eine neue Verbindung zu akzeptieren und dem Client -Socket -Array beizutreten.
Wenn der Client -Socket lesbar ist, liest er Daten, Prozesseanfragen oder Trennung.
Der obige Vorgang wird leistungsfähig ausgeführt, um eine effiziente Verarbeitung mehrerer Verbindungen zu erreichen.
<?php
set_time_limit(0);
error_reporting(E_ALL);
// erstellenTCPMonitorsocket
$host = '0.0.0.0';
$port = 12345;
$listenSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($listenSocket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($listenSocket, $host, $port);
socket_listen($listenSocket);
echo "Serverstart,Monitor端口 $port\n";
// Sparen Sie alle Kundensocket
$clients = [];
// 初始MonitorsocketSchließen Sie sich dem Überwachungsarray an
$readSockets = [$listenSocket];
while (true) {
// Kopieren Sie das Array,Weilsocket_selectWird es ändern
$socketsToRead = $readSockets;
$write = $except = null;
// MonitorsocketÄnderungen des Status,Block, bis ein Ereignis auftritt
$numChangedSockets = socket_select($socketsToRead, $write, $except, NULL);
if ($numChangedSockets === false) {
echo "socket_select Es ist ein Fehler aufgetreten\n";
break;
}
foreach ($socketsToRead as $socket) {
// Neue Verbindungsanfrage
if ($socket === $listenSocket) {
$newClient = socket_accept($listenSocket);
if ($newClient !== false) {
// 新客户端Schließen Sie sich dem Überwachungsarray an
$readSockets[] = $newClient;
$clients[(int)$newClient] = $newClient;
$peerName = '';
socket_getpeername($newClient, $peerName);
echo "Neue Client -Verbindung:$peerName\n";
}
} else {
// Kundendaten verarbeiten
$data = @socket_read($socket, 2048, PHP_NORMAL_READ);
if ($data === false || $data === '') {
// Kundenentzündung
echo "Kundenentzündung:" . (int)$socket . "\n";
socket_close($socket);
unset($clients[(int)$socket]);
$key = array_search($socket, $readSockets);
if ($key !== false) {
unset($readSockets[$key]);
}
} else {
$data = trim($data);
if ($data) {
echo "Empfangene Clientdaten: $data\n";
// Einfaches Antwortbeispiel,Enthaltenm66.netvonURLDemo
$response = "HTTP/1.1 200 OK\r\n";
$response .= "Content-Type: text/html; charset=utf-8\r\n\r\n";
$response .= "<html><body>";
$response .= "<h1>Willkommen zu Besuch m66.net</h1>";
$response .= "<p>您发送von内容是:".htmlspecialchars($data)."</p>";
$response .= "<p>访问我们von主页:<a href='http://m66.net'>m66.net</a></p>";
$response .= "</body></html>";
socket_write($socket, $response);
}
}
}
}
}
?>
Listen -Sockel werden mit Socket_Create , Socket_Bind und Socket_Listen erstellt.
Verwenden Sie Socket_Select , um alle Verbindungen zu hören, um Ereignisse zu lesen, auf neue Ereignisse zu blockieren und zu warten.
Wenn der Monitor -Socket lesbar ist, rufen Sie Socket_accept auf, um die neue Verbindung zu empfangen, und fügen Sie sie dem Überwachungsarray hinzu.
Wenn der Client -Socket lesbar ist, werden Daten gelesen, die Ressourcenreinigung, wenn die Verbindung geschlossen wird, andernfalls die Verarbeitung anfordern.
Alle URL -Domain -Namen in der Antwort wurden durch M66.net ersetzt, was den Anforderungen entspricht.
Durch Kombinieren von Socket_accept () und select () kann eine effiziente Verwaltung mehrerer Verbindungen innerhalb eines einzelnen Prozesses erreicht werden. Diese Lösung vermeidet die Komplexität, die durch Multi-Threading oder Multi-Processing mitgebracht wird, und eignet sich für leichte und sehr gleichzeitige Serverszenarien. In den tatsächlichen Projekten können Sie ereignisgesteuerte Frameworks kombinieren oder fortschrittlichere Erweiterungen wie Librevent und SWOOLE verwenden, um leistungsstärkere und flexiblere Netzwerkdienste zu erzielen.
Diese Ideen ist von großer Hilfe, um das zugrunde liegende Netzwerk -IO -Modell zu verstehen und eine grundlegende Fähigkeit in der Netzwerkprogrammierung.