Autor: Armel Fauveau
Ursprüngliche Adresse: http://www.phpbuilder.net/columns/armel20010427.php3
Übersetzer: Xu [email protected]
Http://www.phpobject.net/blog/
PHP kann Sockets von Remote- oder lokalen Servern öffnen! Hier ist ein einfaches Beispiel für die Verwendung von Sockets: Stellen Sie eine Verbindung zu einem Usenet-Newsserver her, kommunizieren Sie mit dem Server und laden Sie einige Artikel aus einer bestimmten Newsgruppe herunter.
Öffnen Sie Socket mit PHP
Verwenden Sie fsockopen(), um einen Socket zu öffnen. Diese Funktion existiert sowohl in PHP3 als auch in PHP4. Der Prototyp der Funktion lautet wie folgt:
<?php
intfsockopen
(String Hostname,
int port[,
int errno[,
string errstr[,
doppeltes Timeout]]])
?>
Bei Netzwerk-Hosts wird eine TCP-Socket-Verbindung zum Port des Hostnamens hergestellt. Der Hostname kann ein Domänenname oder eine IP-Adresse sein. Für UDP-Verbindungen müssen Sie das Protokoll angeben: udp://hostname. Bei Unix-Hosts wird der Hostname im Pfad zum Socket verwendet und der Port muss in diesem Beispiel auf 0 gesetzt werden. Mit dem optionalen Timeout kann die Anzahl der Sekunden für das Verbindungs-Timeout festgelegt werden.
Weitere Informationen zu fsockopen() finden Sie unter http://www.php.net/manual/function.fsockopen.php
Network News Transfer Protocol (NNTP)
Der Zugriff auf einen Usenet-Newsserver erfordert die Verwendung eines speziellen Protokolls namens NNTP, dem Network News Transfer Protocol-Standard. Die Details dieses Protokolls finden Sie in RFC977, das Sie unter http://www.w3.org/Protocols/rfc977/rfc977.html einsehen können. In diesem Dokument wird ausführlich beschrieben, wie Sie verschiedene Befehle verwenden, um eine Verbindung zu einem NNTP-Server herzustellen und mit ihm zu kommunizieren.
Verbindungsserver Um eine Verbindung zu einem NNTP-Server herzustellen, müssen Sie den Hostnamen (oder die IP-Adresse) des Servers und den Port kennen, den er abhört. Es wird außerdem empfohlen, eine Zeitüberschreitung hinzuzufügen, damit das Programm nicht „einfriert“, wenn die Verbindung fehlschlägt.
<?php
$cfgServer="your.news.host";
$cfgPort =119;
$cfgTimeOut =10;
// einen Socket öffnen
if(!$cfgTimeOut)
// ohne Timeout
$usenet_handle=fsockopen($cfgServer,$cfgPort);
anders
// mit Timeout
$usenet_handle=fsockopen($cfgServer,$cfgPort, &$errno, &$errstr,$cfgTimeOut);
if(!$usenet_handle) {
echo"Verbindung fehlgeschlagenn";
Ausfahrt();
}
anders {
echo"Verbundenn";
$tmp=fgets($usenet_handle,1024);
}
?>
Interaktion mit dem Server Jetzt sind wir mit dem Server verbunden und können über die zuvor geöffnete Socket-Verbindung mit dem Server interagieren. Sagen wir dem Server: „Wir möchten die neuesten 10 Artikel einer bestimmten Newsgruppe erhalten.“ RFC977 definiert den Befehl zur Auswahl der richtigen Nachrichtengruppierung wie folgt:
GRUPPEggg
Der erforderliche Parameter ggg ist der Name der Newsgruppe, die Sie auswählen möchten, z. B. net.news. Mit dem Befehl list können Sie eine gültige Nachrichtenliste erhalten. Bei einer erfolgreichen Auswahlantwort werden die Nachrichtenzahlen der ersten und letzten beiden Nachrichtenartikel in der Gruppe sowie eine Schätzung der archivierten Nachrichtenzahlen zurückgegeben.
Zum Beispiel
chrome:~$ telnetmy.news.host 119
Versuche aa.bb.cc.dd...
Verbunden mit meinem.news.host.
Das Escape-Zeichen ist „^]“.
200 my.news.hostInterNetNews NNRP-Server INN 2.2.2 13. Dezember 1999 bereit (Veröffentlichung ok).
GRUPPE alt.test
211 232 222996 223235alt.test
aufhören
205.
Nach Erhalt des Befehls „GROUP alt.test“ gab der Newsserver „211232 222996 223235 alt.test“ zurück. 211 ist der RFC-Identifikationscode (eine einfache Erklärung dafür, dass der Befehl erfolgreich ausgeführt wurde – überprüfen Sie RFC auf detailliertere Informationen. Die zurückgegebenen Informationen zeigen an, dass es 232 Artikel gibt, von denen die Indexnummer der ältesten Nachricht 222996 ist aktuell Die Nachrichtenindexnummer ist 223235. Jetzt rechnen wir mal durch: 222996+232 ist nicht gleich 232235. Der fehlende Artikel wurde entweder vom Server entfernt, vom Autor gelöscht (ja, das ist möglich und einfach) oder gelöscht.
Als Vorsichtsmaßnahme kann es sein, dass der Server vor der Auswahl einer Newsgruppe eine Authentifizierung erfordert, je nachdem, ob es sich um einen öffentlichen oder einen privaten Server handelt. Grundsätzlich ist es jedem gestattet, Nachrichten zu erhalten, für die Veröffentlichung von Nachrichten ist jedoch eine Zertifizierung erforderlich.
<?php
//$cfgUser = "xxxxxx";
//$cfgPasswd = "yyyyyy";
$cfgNewsGroup="alt.php";
// Identifikation auf privatem Server erforderlich
if($cfgUser) {
fputs($usenet_handle,"AUTHINFO USER".$cfgUser."n");
$tmp=fgets($usenet_handle,1024);
fputs($usenet_handle,"AUTHINFOPASS".$cfgPasswd."n");
$tmp=fgets($usenet_handle,1024);
// Fehler prüfen
if($tmp!="281Okrn") {
echo „502Authentifizierungsfehlern“;
Ausfahrt();
}
}
// Newsgruppe auswählen
fputs($usenet_handle,"GROUP ".$cfgNewsGroup."n");
$tmp=fgets($usenet_handle,1024);
if($tmp=="480 Authentifizierung für Befehl erforderlichrn") {
echo „$tmpn“;
Ausfahrt();
}
$info=split(" ",$tmp);
$first=$info[2];
$last=$info[3];
print"First : $firstn";
print"Letzter: $lastn";
?>
Holen Sie sich einige Artikel Da wir nun die A-Indexnummer des neuesten Artikels haben, können wir ganz einfach die letzten zehn Artikel abrufen. RFC977 besagt, dass der ARTICLE-Befehl mit der Artikelindexnummer oder Nachrichten-ID verwendet werden kann. Aus Vorsichtsgründen sind hier die Indexnummer des Artikels und die Nachrichten-ID unterschiedlich. Da jeder Newsserver unterschiedliche Definitionen hat, ist die Indexnummer desselben Artikels auf verschiedenen Newsservern unterschiedlich, die Nachrichten-ID sollte jedoch unterschiedlich sein einzigartig. (In der Kopfzeile des Artikels enthalten)
<?php
$cfgLimit =10;
// Letzte Artikel hochladen
$boucle=$last-$cfgLimit;
while ($boucle<=$last) {
set_time_limit(0);
fputs($usenet_handle,"ARTICLE$bouclen");
$article="";
$tmp=fgets($usenet_handle,4096);
if(substr($tmp,0,3) !="220") {
echo"+----------------------+n";
echo"Fehler beim Artikel $bouclen";
echo"+----------------------+n";
}
anders {
while($tmp!=".rn") {
$tmp=fgets($usenet_handle,4096);
$article=$article.$tmp;
}
echo"+----------------------+n";
echo"Article$bouclen";
echo"+----------------------+n";
echo"$articlen";
}
$boucle++;
}
?>
Wir bekommen auf diesem Server nur die zehn neuesten Nachrichten dieser Gruppe. Sie können auch den Befehl HEAD verwenden, um die Kopfzeileninformationen des Artikels abzurufen, oder den Befehl BODY, um den Nachrichtentext abzurufen.
Schließen Sie die Verbindung und verwenden Sie die Funktion fclose(), um die Sitzung mit dem NNTP-Server zu beenden. Natürlich können Sie wie folgt eine neue Datei erstellen:
<?php
// Verbindung schließen
fclose($usenet_handle);
?>
Weitere Informationen zu fclose() finden Sie unter: http://www.php.net/manual/function.fclose.php
Fazit In diesem Artikel haben wir nur gezeigt, wie man unter bestimmten Umständen eine Socket-Verbindung öffnet, verwendet und schließt: Stellen Sie eine Verbindung zu einem NNTP-Server her und rufen Sie einige Artikel aus der Newsgroup ab. Das Veröffentlichen eines Artikels auf einem NNTP-Server mit dem POST-Befehl ist nicht viel komplizierter.
Der nächste Schritt besteht also darin, einen News-Client zu schreiben (und etwas Netscape zu entfernen), der problemlos Artikel speichern und sie mithilfe einer Suchmaschine (z. B. htgid, http://www.htdig.org/) indizieren kann, und das muss vorhanden sein Eine WEB-Anwendung, die Stichwortsuchen in Newsgruppen durchführen kann. Hier ist ein Beispiel. Sie können es unter http://www.phpindex.com/ng/ herunterladen.