在PHP中使用Sockets:從Usenet中獲取檔案

日期:2008-07-09  作者:喜騰小二  來源:PHPChina


作者:Armel Fauveau 原文地址:http://www.phpbuilder.net/columns/armel20010427.php3譯者:許立強feifengxlq@gmail.comHttp://www.phpobject.net/blog/
 PHP能夠開啟遠端或者本機伺服器的sockets!這裡是一個使用socket的簡單的例子:連線到Usenet的新聞伺服器,與伺服器溝通,並從一個精確的新聞分組中下載一些文章。 

使用PHP開啟Socket

使用fsockopen()來開啟一個Socket。這個函式在PHP3PHP4中都存在。函式的原型如下:

intfsockopen
    (string hostname,
        int port [,
        int errno [,
        string errstr [,
        double timeout]]])
?>對於網路主機,它將建立一個TCPSocket的連線到主機名的連接埠上。主機名可以是網域名稱或者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地址)和它將要監聽的連接埠。另外建議妳加上一個逾時的時間,這樣連線失敗的時候就不會“凍結”程式。
$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"Connexionfailed
"
;

    exit();
}    
else {
    echo"Connected
"
;

    $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”。其中211RFC標識碼(簡單的解釋說指令已經成功的執行—檢視RFC妳可以獲取更加詳細的資料),返回資訊幫助其中有232篇文章,其中最舊的新聞的索引號是222996,而最新的新聞索引號是223235。現在讓我們計算下:222996+232並不等於232235。這丟失的文章或者從這伺服器移除出去了,或者被他的作者取消了(是的,這是可能的,也是很容易實現的),或者是移除了。小心起見,在選擇新聞分組之前,伺服器可能需要認證,當然這是由伺服器是否公開或者私有來決定的。一般是允許任何人獲取新聞,但發表新聞需要透過認證。
//$cfgUser    = "xxxxxx";
//$cfgPasswd    = "yyyyyy";
$cfgNewsGroup    = "alt.php";
// identification required on private server
if($cfgUser) {
    fputs($usenet_handle, "AUTHINFO USER".$cfgUser."
"
);
    $tmp = fgets($usenet_handle, 1024);
    fputs($usenet_handle, "AUTHINFOPASS ".$cfgPasswd."
"
);
    $tmp = fgets($usenet_handle, 1024);
    // check error
    if($tmp != "281Ok
"
) {
        echo "502Authentication error
"
;
        exit();
    }    
}
// select newsgroup
fputs($usenet_handle, "GROUP ".$cfgNewsGroup."
"
);
$tmp = fgets($usenet_handle, 1024);
if($tmp == "480 Authentication required for command
"
) {
    echo "$tmp ";
    exit();
}    
$info = split(" ", $tmp);
$first = $info[2];
$last = $info[3];

print "First : $first ";
print "Last : $last ";
?> 獲取一些文章現在我們已經有最新文章的A索引號,那就能很容易的獲取最新的十篇文章。RFC977指出使用ARTICLE指令可以和文章的索引號或者訊息的ID一起使用。為了小心起見,在這裡,文章的索引號和訊息ID是不同的,因為每個新聞伺服器定義不同,所以在不同的新聞伺服器上相同文章的索引號都會不一樣的,但是訊息ID好是唯一的(包含在文章的頭部中)
$cfgLimit    = 10;
// upload last articles
$boucle=$last-$cfgLimit;
while ($boucle <= $last) {
    set_time_limit(0);
    fputs($usenet_handle, "ARTICLE$boucle ");    
    $article="";
    $tmp = fgets($usenet_handle, 4096);
    if(substr($tmp,0,3) != "220") {
        echo "+----------------------+
"
;
        echo "Error onarticle $boucle ";
        echo "+----------------------+
"
;
    }
    else {
        while($tmp!=".
"
) {
            $tmp = fgets($usenet_handle, 4096);
            $article = $article.$tmp;
        }        
        echo "+----------------------+
"
;
        echo "Article$boucle ";
        echo "+----------------------+
"
;
        echo "$article ";
    }    
    $boucle++;
}
?>我們僅僅從這個伺服器的這個分組上獲取了十條最新的新聞。妳也可以使用HEAD指令來至獲取文章的頭部資訊,或者使用BODY指令來獲取新聞的內文。 關閉連線使用fclose()函式妳就可以結束與NNTP伺服器之間的工作階段,當然妳可以些一個新的檔案,如下:
// close connexion
fclose($usenet_handle);
?>更多關於fclose()的資訊,請看:http://www.php.net/manual/function.fclose.php 結論本文中,我們隻幫助了在確定的情況下如何開啟、使用和關閉一個socket連線:連線上一個NNTP伺服器然後從新聞分組中取回一些文章。使用POST指令在NNTP伺服器上發表一篇文章並不復雜多少。因此,下一步就是編寫一個新聞用戶端(並去掉一些Net

<<<返回技術中心

技術文章

站內新聞