PHP getservbyname() Funktion: Alles, was Sie wissen müssen
Als PHP-Entwickler müssen Sie möglicherweise die Portnummer eines Dienstnamens ermitteln. Dabei hilft die PHP-Funktion getservbyname().
Netzwerkdienste werden durch bekannte Namen wie http, ftp oder smtp identifiziert, doch das Betriebssystem leitet den Datenverkehr tatsächlich über Portnummern (80, 21, 25 usw.) weiter. Die PHP-Funktion getservbyname() sucht diese Portnummer für Sie heraus und liest dabei dieselbe Dienstdatenbank, die auch das restliche System verwendet. Diese Seite erläutert die Syntax, was die Datenbank enthält, häufige Anwendungsfälle und mögliche Fallstricke.
Syntax
getservbyname(string $service, string $protocol): int|falseDie Funktion erwartet zwei erforderliche Parameter:
$service— der Name des Internetdienstes, zum Beispiel"http","ssh"oder"smtp".$protocol— das Transportprotokoll, entweder"tcp"oder"udp". Entgegen vieler älterer Dokumentationen ist dieses Argument nicht optional; Sie müssen es übergeben.
Sie gibt die Portnummer als Integer zurück, wenn der Vorgang erfolgreich ist, oder false, wenn das Dienst-/Protokollpaar nicht gefunden wird. Da false und eine gültige Portnummer beide als "falsy-ähnlich" erscheinen können, sollten Sie beim Prüfen auf Fehler immer den strikten Operator === verwenden.
Woher stammen die Daten?
getservbyname() stellt keine Verbindung her und rät nicht. Sie liest eine lokale Nachschlagetabelle:
- Unter Linux und macOS ist dies die Datei
/etc/services. - Unter Windows ist es
%SystemRoot%\system32\drivers\etc\services.
Wenn ein Dienst in dieser Datei fehlt, schlägt die Abfrage fehl, auch wenn der Dienst "offensichtlich" existiert. Das Ergebnis ist daher eine Eigenschaft des Rechners, auf dem das Skript ausgeführt wird, keine universelle Konstante.
Ein einfaches Beispiel
Die Prüfung mit === false ist wichtig: Sie trennt einen echten Fehler klar von einem legitimen Ergebnis wie Port 0 (der bei einem losen ==-Vergleich als falsy gelten würde).
Mehrere Dienste abfragen
In der Praxis lösen Sie oft eine Reihe von Namen auf einmal auf — zum Beispiel um einen Firewall-Bericht zu erstellen oder eine Konfiguration zu validieren:
<?php
$services = ["http", "https", "ftp", "smtp", "ssh"];
foreach ($services as $name) {
$port = getservbyname($name, "tcp");
echo $port === false
? "{$name}: not found\n"
: "{$name}: {$port}\n";
}
/*
Output:
http: 80
https: 443
ftp: 21
smtp: 25
ssh: 22
*/TCP vs. UDP
Derselbe Dienstname kann je nach Protokoll zu unterschiedlichen Einträgen aufgelöst werden, und einige Dienste existieren nur für eines der beiden. Übergeben Sie immer das Protokoll, das Sie tatsächlich benötigen:
<?php
var_dump(getservbyname("domain", "tcp")); // int(53) — DNS over TCP
var_dump(getservbyname("domain", "udp")); // int(53) — DNS over UDP
var_dump(getservbyname("ntp", "udp")); // int(123)
var_dump(getservbyname("madeup", "tcp")); // bool(false) — unknown serviceWann würde ich das verwenden?
- Dynamisches Erstellen von Netzwerk-Clients. Lösen Sie einen Dienstnamen in einen Port auf, bevor Sie mit
fsockopen()oderpfsockopen()einen Socket öffnen, damit Ihr Code"smtp"anstelle einer magischen25enthält. - Konfiguration validieren. Bestätigen Sie, dass ein Dienstname aus einer Konfigurationsdatei dem Host tatsächlich bekannt ist, bevor Sie ihn verwenden.
- Reporting / Tooling. Wandeln Sie benutzerfreundliche Dienstnamen für Logs, Dashboards oder Firewall-Regeln in Ports um.
Verwandte Funktionen
getservbyport()— die Umkehrfunktion: gibt zu einer Portnummer und einem Protokoll den Dienstnamen zurück.getprotobyname()— sucht eine Protokollnummer (z. B.tcp→6) anhand ihres Namens.
Häufige Fallstricke
- Beide Argumente sind erforderlich. Das Weglassen von
$protocolverursacht einen Fehler; es gibt keinen impliziten Standardwert. - Nur strikter Vergleich. Verwenden Sie
=== false, um Fehler zu erkennen, damit Port0oder ein numerischer Sonderfall nicht falsch interpretiert wird. - Hostabhängige Ergebnisse. Die Antwort kommt aus der lokalen Dienstdatenbank; ein Name, der einem Rechner unbekannt ist, kann auf einem anderen auflösbar sein.
- Keine Netzwerkverbindung. Kein DNS, kein Netzwerk — nur eine lokale Tabellenabfrage, daher schnell und sicher für häufige Aufrufe.
Zusammenfassung
getservbyname() ordnet einem Dienstnamen und Protokoll mithilfe der Dienstdatenbank des Betriebssystems eine Portnummer zu und gibt einen Integer-Port oder false zurück, wenn das Paar unbekannt ist. Kombinieren Sie sie mit getservbyport() für die umgekehrte Richtung und mit fsockopen(), wenn Sie diesen Port in eine tatsächliche Verbindung umwandeln möchten.