|
原文地址:http://www.phpbuilder.NET/columns/armel20010427.php3
php能夠打開(kāi)遠(yuǎn)程或者本地服務(wù)器的sockets!這里是一個(gè)使用socket的簡(jiǎn)單的例子:連接到UseNET的新聞服務(wù)器,與服務(wù)器溝通,并從一個(gè)精確的新聞分組中下載一些文章。
使用php打開(kāi)Socket
使用fsockopen()來(lái)打開(kāi)一個(gè)Socket。這個(gè)函數(shù)在php3和php4中都存在。函數(shù)的原型如下:
<?php
intfsockopen
(string hostname,
int port [,
int errno [,
string errstr [,
double timeout]]])
?>
對(duì)于網(wǎng)絡(luò)主機(jī),它將建立一個(gè)TCP的Socket的連接到主機(jī)名的端口上。主機(jī)名可以是域名或者IP地址。對(duì)于UDP連接,你需要明確指出其協(xié)議:udp://hostname。對(duì)于unix主機(jī),主機(jī)名將在socket的路徑中使用,在這個(gè)例子中端口必須設(shè)置成0。可選項(xiàng)timeout可以用來(lái)設(shè)置連接超時(shí)的秒數(shù)。
關(guān)于fsockopen()的更多信息可以訪問(wèn)http://www.php.NET/manual/function.fsockopen.php
網(wǎng)絡(luò)新聞傳輸協(xié)議(NNTP)
訪問(wèn)一個(gè)useNET新聞服務(wù)器需要用到一個(gè)特別的協(xié)議,稱作NNTP,即網(wǎng)絡(luò)新聞傳輸協(xié)議標(biāo)準(zhǔn)。這個(gè)協(xié)議的詳細(xì)資料在RFC977中,你可以在http://www.w3.org/Protocols/rfc977/rfc977.html中查看到。這個(gè)文檔詳細(xì)的描述了如何使用不同的命令來(lái)連接并且和NNTP服務(wù)器對(duì)話。
連接服務(wù)器
連接到NNTP服務(wù)器需要知道服務(wù)器的主機(jī)名(或者IP地址)和它將要監(jiān)聽(tīng)的端口。另外建議你加上一個(gè)超時(shí)的時(shí)間,這樣連接失敗的時(shí)候就不會(huì)“凍結(jié)”程序。
<?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"Connexionfailed/n";
exit();
}
else {
echo"Connected/n";
$tmp = fgets($useNET_handle, 1024);
}
?>
與服務(wù)器交互
現(xiàn)在我們已經(jīng)連接上服務(wù)器了,而且能夠通過(guò)先前打開(kāi)的socket連接與服務(wù)器進(jìn)行交互。讓我們對(duì)服務(wù)器說(shuō)“我們要從某一新聞分組中獲取到最新的10篇文章”。RFC977定義了如何選擇正確的新聞分組的命令,如下:
GROUPggg
必需的參數(shù)ggg是你將要選擇的新聞分組的名字,比如NET.news。使用list命令你可以獲取到一組有效的新聞列表。成功選擇響應(yīng)會(huì)返回組中首尾兩篇新聞的新聞號(hào)以及對(duì)存檔新聞號(hào)估計(jì)。
比如
chrome:~$ telNETmy.news.host 119
Trying 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.test
211 232 222996 223235alt.test
quit
205 .
在接受到命令“GROUP alt.test”,新聞服務(wù)器返回了“211232 222996 223235 alt.test”。其中211是RFC標(biāo)識(shí)碼(簡(jiǎn)單的解釋說(shuō)命令已經(jīng)成功的執(zhí)行―查看RFC你可以獲取更加詳細(xì)的資料),返回信息說(shuō)明其中有232篇文章,其中最舊的新聞的索引號(hào)是222996,而最新的新聞索引號(hào)是223235。現(xiàn)在讓我們計(jì)算下:222996+232并不等于232235。這丟失的文章或者從這服務(wù)器移除出去了,或者被他的作者取消了(是的,這是可能的,也是很容易實(shí)現(xiàn)的),或者是刪除了。
小心起見(jiàn),在選擇新聞分組之前,服務(wù)器可能需要認(rèn)證,當(dāng)然這是由服務(wù)器是否公開(kāi)或者私有來(lái)決定的。一般是允許任何人獲取新聞,但發(fā)表新聞需要通過(guò)認(rèn)證。
<?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 != "281Ok/r/n") {
echo "502Authentication error/n";
exit();
}
}
// select newsgroup
fputs($useNET_handle, "GROUP ".$cfgNewsGroup."/n");
$tmp = fgets($useNET_handle, 1024);
if($tmp == "480 Authentication required for command/r/n") {
echo "$tmp/n";
exit();
}
$info = split(" ", $tmp);
$first = $info[2];
$last = $info[3];
print "First : $first/n";
print "Last : $last/n";
?>
獲取一些文章
現(xiàn)在我們已經(jīng)有最新文章的A索引號(hào),那就能很容易的獲取最新的十篇文章。RFC977指出使用ARTICLE命令可以和文章的索引號(hào)或者消息的ID一起使用。為了小心起見(jiàn),在這里,文章的索引號(hào)和消息ID是不同的,因?yàn)槊總€(gè)新聞服務(wù)器定義不同,所以在不同的新聞服務(wù)器上相同文章的索引號(hào)都會(huì)不一樣的,但是消息ID好是唯一的(包含在文章的頭部中)
<?php
$cfgLimit = 10;
// upload last articles
$boucle=$last-$cfgLimit;
while ($boucle <= $last) {
set_time_limit(0);
fputs($useNET_handle, "ARTICLE$boucle/n");
$article="";
$tmp = fgets($useNET_handle, 4096);
if(substr($tmp,0,3) != "220") {
echo "+----------------------+/n";
echo "Error onarticle $boucle/n";
echo "+----------------------+/n";
}
else {
while($tmp!="./r/n") {
$tmp = fgets($useNET_handle, 4096);
$article = $article.$tmp;
}
echo "+----------------------+/n";
echo "Article$boucle/n";
echo "+----------------------+/n";
echo "$article/n";
}
$boucle++;
}
?>
我們僅僅從這個(gè)服務(wù)器的這個(gè)分組上獲取了十條最新的新聞。你也可以使用HEAD命令來(lái)至獲取文章的頭部信息,或者使用BODY命令來(lái)獲取新聞的正文。
關(guān)閉連接
使用fclose()函數(shù)你就可以結(jié)束與NNTP服務(wù)器之間的會(huì)話,當(dāng)然你可以些一個(gè)新的文件,如下:
<?php
// close connexion
fclose($useNET_handle);
?>
更多關(guān)于fclose()的信息,請(qǐng)看:http://www.php.NET/manual/function.fclose.php
結(jié)論
本文中,我們只說(shuō)明了在確定的情況下如何打開(kāi)、使用和關(guān)閉一個(gè)socket連接:連接上一個(gè)NNTP服務(wù)器然后從新聞分組中取回一些文章。使用POST命令在NNTP服務(wù)器上發(fā)表一篇文章并不復(fù)雜多少。
因此,下一步就是編寫一個(gè)新聞客戶端(并去掉一些NETscape),它需要能很容易的保存文章,并使用一些搜索引擎(比如htgid, http://www.htdig.org/)來(lái)索引這些文章,而且要有一個(gè)WEB應(yīng)用程序能進(jìn)行新聞分組下的關(guān)鍵字搜索。這里有一個(gè)例子,你可以訪問(wèn)http://www.phpindex.com/ng/去下載。
php技術(shù):在PHP中使用Sockets 從Usenet中獲取文件,轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。