fsockopen通信过程中反复fputs,fgets的问题[我没招了]

gu1dai 2005-12-02 06:32:16
fsockopen打开一个url,
fputs发送请求。
while(!feof($fp)) fgets();

这是正常的步骤。
现在要反复请求那个url。
for($i=0;$i<8;$i++){
fputs发送请求。
while(!feof($fp)) fgets();
}

除了第一次得到了返回外,后续的几次都只能得到空。我的理解是:第一次请求返回数据的结尾就是eof标记。所以第二次指针指向的正好是这个eof,所以就跳不过去,所以就无法得到数据。

根据这个理解,我想出的解决办法。
---------------------
在while!feof之前加个fgets,让指针跳过这个eof标记。
fgets($fp,4096);
while(!feof....)

然而事实无情地击碎了我的猜测。得到的数据依然是空,在循环里echo,可以发现没有任何输出,就是循环没有进入。

----------------
我的理解是第一次取完返回数据的时候,文件指针的eof标记就被设定当前为真。以后的feof就取这个真值,而非再次进行判断。

----------------------
下面是我的解决办法
...全文
491 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
gu1dai 2005-12-05
  • 打赏
  • 举报
回复
这是因为你不了解HTTP协议,HTTP每次连接只能请求一次,请求结束服务器自动关闭连接的,你是不能再做请求的。

---------
再做请求是没有任何问题的。在请求的头里将Connection设置为keep-alive即可。
-----------------
头大了。有部分服务器可以正确地得到数据了,比如google,csdn。然而winzheng.com的,baidu的都不行。
----------------------------------
我的解决思路是。用fgets得到响应的头部,从头部中取得当前返回的字节数a。
根据这个数字a/4096得到循环次数n,用fread请求n次,a%4096得到余数mb,用fread请求mb个字节。
最后用fread请求7个字节。这7个字节我认为是服务器返回的终结字符,是我反复测试得到的。
这样做的结果是google和我本地的服务器以及csdn都可以正确地得到数据。
bbs.winzheng.com和baidu的都不行。
-神仙- 2005-12-03
  • 打赏
  • 举报
回复
楼上抢先了。。。。。
你的问题本来是办不到的。
Meteorlet 2005-12-03
  • 打赏
  • 举报
回复
这是因为你不了解HTTP协议,HTTP每次连接只能请求一次,请求结束服务器自动关闭连接的,你是不能再做请求的。
gu1dai 2005-12-03
  • 打赏
  • 举报
回复
我已经说了,反复调用fsockopen则是进行不同的会话。
必须保证在一次fsockopen的过程中进行数次请求。

while !feof不行才来求助的。
gu1dai 2005-12-03
  • 打赏
  • 举报
回复
http协议我的确不了解,我只是想模拟一次浏览器和服务器的会话过程,谢谢各位兄弟。
gu1dai 2005-12-03
  • 打赏
  • 举报
回复
模拟一次会话,只需处理传来的头部,将session什么的放在下次请求的头里即可。
我已经似乎解决了这个问题。测试本地的apache服务器没有问题,正在处理细节。
aiiiq 2005-12-02
  • 打赏
  • 举报
回复
"现在要反复请求那个url。"

你应该反复调用fsockopen

调用一次fsockopen相当于创建一次socket

也可以用socket function但是不好控制

function f_socket($website,$url)
{
$service_port = getservbyname('www', 'tcp');
$address = gethostbyname($website);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$socket_result = socket_connect($socket, $address, $service_port))

$in = "GET " . $url . " HTTP/1.1\r\n";
$in .= "Host: " . $website . "\r\n";
$in .= "Connection: close\r\n\r\n";
socket_write($socket, $in, strlen($in));
$str = "";
do
{
if (false === ($out = socket_read($socket, 1024)))
{
$str = "";
break;
}
$str .= $out;
} while ($out != "");
socket_close($socket);
return $str;
}
aiiiq 2005-12-02
  • 打赏
  • 举报
回复
代码贴上来

最终需要什么结果?

我每次读8192字节,直到没有

还有啊分太少,呵呵

function f_fsock($website,$url)
{
$fp = fsockopen($website, 80, $errno, $errstr, 30);
if ($fp)
{
$out = "GET " . $url . " HTTP/1.1\r\n";
$out .= "Host: " . $website . "\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
$str = "";
while (!feof($fp))
{
stream_set_timeout($fp, 200);
$str .= fread($fp, 8192);
$info = stream_get_meta_data($fp);
if ($info['timed_out'])
{
$str = "";
break;
}
}
fclose($fp);

// 去掉http头
preg_match("/\r\n\r\n(.+)/is", $str, $out);
$str = $out[1];
return $str;
}
}
gu1dai 2005-12-02
  • 打赏
  • 举报
回复
fseek和另一个函数都不行。我试过的。

帮帮我。如果实在不行,我就采用遇到\r\n+1的办法来控制指针。
gu1dai 2005-12-02
  • 打赏
  • 举报
回复
我黔驴技穷了。
zalvsa 2005-12-02
  • 打赏
  • 举报
回复
问题是指针已经到文件尾了,你要么重新读,要么指针定位。
当 fp 由 fopen() 打开 "http://...." 或是 "ftp://...." 等 URL 文件时,本函数无法作用。也适用与fsockopen吗?我不清楚哦,可能你要试一下。
gu1dai 2005-12-02
  • 打赏
  • 举报
回复
fseek和另一个函数是定位指针的,不能用于url.

关闭fsockopen打开的指针,再打开,这个办法不是我要的,因为要在一次session会话中完成任务。
zalvsa 2005-12-02
  • 打赏
  • 举报
回复
我没用过这些通讯函数,可是照手册上说的及你的写法。实际上是对$fp进行数据请求,那第一次都已经执行到$fp的数据尾了,你没再重新对$fp进行赋值或者指针定位,那肯定后面的都读到空值了。
gu1dai 2005-12-02
  • 打赏
  • 举报
回复
服务器返回的响应中包含了当前返回内容的长度。
iis返回一个content-length.根据这个长度来循环,每遇到一个\r\n就加1。遇不到则跳出。
这样文件指针就不会错误地被指向远处。或者没有达到结尾就结束。

然而。如果服务器输出的内容的所有行并不都包含\r\n呢。

我不知道怎么解决。请各位兄弟指点迷津。

21,891

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧