在PHP 5.x中使用fsockopen循环获取Fget

3
我终于成功编写了一个Python服务器,并能够响应多个命令并返回输出结果,但是我现在遇到了PHP无法接收完整输出的问题。我尝试过使用fgets和fread等命令,但似乎只有“fgets”命令有效。
然而,这个命令只能接收一行数据,所以我创建了下面的while语句:
 while (!feof($handle)) {
    $buffer = fgets($handle, 4096);
    echo $buffer;
}

然而,看起来Python服务器没有在输出的末尾发送Feof,因此php页面会超时并且不显示任何内容。就像我上面所说的,仅运行echo fgets($handle)即可正常工作,并输出一行,再次在其中一个下运行命令将显示下一行等等。
我已经附上了我的Python脚本的重要部分:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("", port))
s.listen(5)
print "OK."
print "  Listening on port:", port
import subprocess
while 1:
    con, addr = s.accept()
    while True:
        datagram = con.recv(1024)
        if not datagram:
            break
        print "Rx Cmd:", datagram
        print "Launch:", datagram
        process = subprocess.Popen(datagram+" &", shell=True, stdout=subprocess.PIPE)
        stdout, stderr = process.communicate()
        con.send(stdout)
    con.close()
s.close()

我也附上了完整的PHP脚本:
<?php
$handle = fsockopen("tcp://xxx.xxx.xxx.xxx",12345);
fwrite($handle,"ls");
echo fgets($handle);
fclose($handle);
?>

感谢您,Ashley。
1个回答

1

我相信你需要稍微修复一下你的服务器代码。我已经移除了内部的 while 循环。你的代码问题在于服务器从未关闭连接,所以 feof 从未返回 true。

我还移除了 + " &" 部分。无论如何,要获取输出,你都需要等待进程结束。而且我不确定 shell 在这种情况下会如何处理 &

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("", port))
s.listen(5)
print "OK."
print "  Listening on port:", port
import subprocess
try:
    while 1:
        con, addr = s.accept()
        try:
            datagram = con.recv(1024)
            if not datagram:
                continue
            print "Rx Cmd:", datagram
            print "Launch:", datagram
            process = subprocess.Popen(datagram, shell=True, stdout=subprocess.PIPE)
            stdout, stderr = process.communicate()
            con.send(stdout)
        finally:
            print "closing connection"
            con.close()
except KeyboardInterrupt:
    pass
finally:
    print "closing socket"
    s.close()

顺便提一下,你需要在你的 PHP 脚本中使用 while 循环。fgets 只返回单行。


工作得非常好,谢谢。最后一个问题,目前当我使用Cntrl+C关闭程序时,它并没有干净地关闭部分内容。我考虑运行一个while语句来检测cntr+某些操作,然后关闭套接字。但我不知道是否可以在运行软件的while语句的同时执行这个操作。 - AshleyUK
我猜你指的是服务器程序,而不是 PHP 客户端?在这种情况下,我相信最后一个 finally 子句中的 s.close() 应该在使用 Ctrl-C 时关闭套接字。当你使用 Ctrl-C 退出服务器时,你应该在控制台上看到 "closing socket" 的输出。你没有看到吗? - codeape
当我使用Cntrl+C时,我会得到以下信息:Traceback (most recent call last): File "vzctl.py", line 15, in <module> con, addr = s.accept() File "/usr/local/lib/python2.5/socket.py", line 167, in accept sock, addr = self._sock.accept() KeyboardInterrupt现在它确实释放了套接字,自从您更改了代码以来,我还没有完全测试过它,但是我不确定关闭套接字后显示的错误是否正确? - AshleyUK
在Python程序中,按下Ctrl-C会引发KeyboardInterrupt。我已经在服务器代码中添加了一个except子句来处理这个异常(通过什么也不做来处理)。 - codeape
现在工作完美了。谢谢Codeape。 - AshleyUK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接