作者: Armel Fauveau
PHP 能够打开远程或者本地服务器的 sockets! 这里是一个使用 socket 的简单的例子: 连接到 Usenet 的新闻服务器, 与服务器沟通, 并从一个精确的新闻分组中下载一些文章
使用 PHP 打开 Socket
使用 fsockopen()来打开一个 Socket 这个函数在 PHP3 和 PHP4 中都存在函数的原型如下:
- 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 地址) 和它将要监听的端口另外建议你加上一个超时的时间, 这样连接失败的时候就不会冻结程序
- $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);
- }
- ?>
与服务器交互
现在我们已经连接上服务器了, 而且能够通过先前打开的 socket 连接与服务器进行交互让我们对服务器说我们要从某一新闻分组中获取到最新的 10 篇文章 RFC977 定义了如何选择正确的新闻分组的命令, 如下:
GROUPggg
必需的参数 ggg 是你将要选择的新闻分组的名字, 比如 net.news 使用 list 命令你可以获取到一组有效的新闻列表成功选择响应会返回组中首尾两篇新闻的新闻号以及对存档新闻号估计
比如
- 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, 新闻服务器返回了 211232 222996 223235 alt.test 其中 211 是 RFC 标识码(简单的解释说命令已经成功的执行查看 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."\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";
- ?>
获取一些文章
现在我们已经有最新文章的 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\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++;
- }
- ?>
我们仅仅从这个服务器的这个分组上获取了十条最新的新闻你也可以使用 HEAD 命令来至获取文章的头部信息, 或者使用 BODY 命令来获取新闻的正文
关闭连接
使用 fclose()函数你就可以结束与 NNTP 服务器之间的会话, 当然你可以些一个新的文件, 如下:
- // close connexion
- fclose($usenet_handle);
- ?>
更多关于 fclose()的信息, 请看: http://www.php.net/manual/function.fclose.php
结论
本文中, 我们只说明了在确定的情况下如何打开使用和关闭一个 socket 连接: 连接上一个 NNTP 服务器然后从新闻分组中取回一些文章使用 POST 命令在 NNTP 服务器上发表一篇文章并不复杂多少
因此, 下一步就是编写一个新闻客户端 (并去掉一些 Netscape), 它需要能很容易的保存文章, 并使用一些搜索引擎(比如 htgid, http://www.htdig.org/) 来索引这些文章, 而且要有一个 web 应用程序能进行新闻分组下的关键字搜索这里有一个例子, 你可以访问 http://www.phpindex.com/ng / 去下载
来源: https://www.php1.cn/detail/php-5e626da811.html