php fsockopen() Us.net中擷取檔案
開啟Socket
使用fsockopen()來開啟一個Socket。這個函數在PHP3和PHP4中都存在。函數的原型如下:<?php
intfsockopen
(string hostname,
int port [,
int errno [,
string errstr [,
double timeout]]])
?>對於網路主機,它將建立一個TCP的Socket的串連到主機名稱的連接埠上。主機名稱可以是網域名稱或者IP地址。對於UDP串連,你需要明確指出其協議:udp://hostname。對於unix主機,主機名稱將在socket的路徑中使用,在這個例子中連接埠必須設定成0。可選項timeout可以用來設定連線逾時的秒數。關於fsockopen()的更多資訊可以訪問http://www.php.net/manual/function.fsockopen.php 網路新聞傳輸通訊協定(NNTP)訪問一個usenet新聞伺服器需要用到一個特別的協議,稱作NNTP,即網路新聞傳輸通訊協定標準。這個協議的詳細資料在RFC977中,你可以在http://www.w3.org/Protocols/rfc977/rfc977.html中查看到。這個文檔詳細的描述了如何使用不同的命令來串連並且和NNTP伺服器對話。 串連伺服器串連到NNTP伺服器需要知道伺服器的主機名稱(或者IP地址)和它將要監聽的連接埠。另外建議你加上一個逾時的時間,這樣串連失敗的時候就不會“凍結”程式。<?php
$cfgServer = "your.news.host";
$cfgPort = 119;
$cfgTimeOut = 10;
// open asocket
if(!$cfgTimeOut)
// without timeout
$usenet_handle = fsockopen($cfgServer, $cfgPort);
else
// with timeout
$usenet_handle = fsockopen($cfgServer, $cfgPort, &$errno, &$errstr, $cfgTimeOut);
if(!$usenet_handle) {
echo"Connexionfailedn";
exit();
}
else {
echo"Connectedn";
$tmp = fgets($usenet_handle, 1024);
}
?> 與伺服器互動現在我們已經串連上伺服器了,而且能夠通過先前開啟的socket串連與伺服器進行互動。讓我們對伺服器說“我們要從某一新聞分組中擷取到最新的10篇文章”。RFC977定義了如何選擇正確的新聞分組的命令,如下:GROUPggg必要參數ggg是你將要選擇的新聞分組的名字,比如net.news。使用list命令你可以擷取到一組有效新聞列表。成功選擇響應會返回組中首尾兩篇新聞的新聞號以及對存檔新聞號估計。比如 chrome:~$ telnetmy.news.host 119Trying aa.bb.cc.dd...Connected tomy.news.host.Escape character is‘^]‘.200 my.news.hostInterNetNews NNRP server INN 2.2.2 13-Dec-1999 ready (posting ok).GROUP alt.test211 232 222996 223235alt.testquit205 .在接受到命令“GROUP alt.test”,新聞伺服器返回了“211232 222996 223235 alt.test”。其中211是RFC標識碼(簡單的解釋說命令已經成功的執行—查看RFC你可以擷取更加詳細的資料),返回資訊說明其中有232篇文章,其中最舊的新聞的索引號是222996,而最新的新聞索引號是223235。現在讓我們計算下:222996+232並不等於232235。這丟失的文章或者從這伺服器移除出去了,或者被他的作者取消了(是的,這是可能的,也是很容易實現的),或者是刪除了。小心起見,在選擇新聞分組之前,伺服器可能需要認證,當然這是由伺服器是否公開或者私人來決定的。一般是允許任何人擷取新聞,但發表新聞需要通過認證。<?php
//$cfgUser = "xxxxxx";
//$cfgPasswd = "yyyyyy";
$cfgNewsGroup = "alt.php";
// identification required on private server
if($cfgUser) {
fputs($usenet_handle, "AUTHINFO USER".$cfgUser."n");
$tmp = fgets($usenet_handle, 1024);
fputs($usenet_handle, "AUTHINFO PASS ".$cfgPasswd."n");
$tmp = fgets($usenet_handle, 1024);
// check error
if($tmp != "281Okrn") {
echo "502Authentication errorn";
exit();
}
}
// select newsgroup
fputs($usenet_handle, "GROUP ".$cfgNewsGroup."n");
$tmp = fgets($usenet_handle, 1024);
if($tmp == "480 Authentication required for commandrn") {
echo "$tmpn";
exit();
}
$info = split(" ", $tmp);
$first = $info[2];
$last = $info[3];
print "First : $firstn";
print "Last : $lastn";
?> 擷取一些文章現在我們已經有最新文章的A索引號,那就能很容易的擷取最新的十篇文章。RFC977指出使用ARTICLE命令可以和文章的索引號或者訊息的ID一起使用。為了小心起見,在這裡,文章的索引號和訊息ID是不同的,因為每個新聞伺服器定義不同,所以在不同的新聞伺服器上相同文章的索引號都會不一樣的,但是訊息ID好是唯一的(包含在文章的頭部中)<?php
$cfgLimit = 10;
// upload last articles
$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 "Error onarticle $bouclen";
echo "+----------------------+n";
}
else {
while($tmp!=".rn") {
$tmp = fgets($usenet_handle, 4096);
$article = $article.$tmp;
}
echo "+----------------------+n";
echo "Article$bouclen";
echo "+----------------------+n";
echo "$articlen";
}
$boucle++;
}
?>