在PHP中实现持久化本地域套接字

4
我发现这个问题的答案(例如这里这里这里)都涉及pfsockopen(),它似乎专为非本地套接字连接而设计。然而,我到目前为止编写的代码使用php通过本地连接访问C++服务器。我希望这个连接是持久的(顺便提一下,这样我就可以用它来进行Comet)。以下是我的非持久版本:
<?php
session_start();

...

if (($sock = socket_create(AF_UNIX, SOCK_STREAM,0)) === false)
{
echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
        exit();
}
$sess_id = $_SESSION['sess_id'];
$sock_str = '/tmp/sockdir/' . $sess_id; //The socket is named after the php session, not important
if (socket_connect($sock, $sock_str) === false)
{
        echo "socket_connect() to " . $sock_str . " failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
        socket_close($sock);
        exit();
}

$msg = $_GET['message'];

// ... do things with $msg

socket_close($sock);
?>

我发现不能简单地将'$sock'保存为$_SESSION变量并在每次调用此脚本时访问它。有什么窍门可以把它转化为持久连接吗?


1
这里的问题在于请求是有状态的 - 当请求处于活动状态时,您的PHP应用程序仅在内存中运行。为什么需要持久连接? - tkone
@tkone 我需要网页能够独立于特定客户端请求而响应服务器生成的消息。这是常见的功能需求,例如这里所述;这也被称为服务器端事件。 - Matt Phillips
所以你正在寻找Websockets?“页面”需要做些什么?这是否意味着页面已经在客户端上加载了?你有考虑过使用socket.io吗?它还没有PHP服务器实例,但它可能会对你有所帮助。或者只需研究支持Websockets或Ajax长轮询等技术。 - tkone
@tkone 我知道WebSockets,但我希望能够修改我已经编写的内容。安装WS服务器(并使其与我的C++后端进行接口!)将是一项巨大的任务。长轮询对我来说似乎太过于hack了,但sockets.io看起来很有趣,谢谢你的提示。我也在研究Node.js。如果我有进展,我会更新这个线程。 - Matt Phillips
1
你总是在最后关闭:socket_close($sock);。可能这就是导致你的问题的原因? - hakre
显示剩余2条评论
2个回答

4
如您提供的链接所指出,php不是一种持久性语言,没有办法在会话(即页面加载)之间保持持久性。但是,您可以通过运行第二个php脚本作为守护进程来创建中间地带,并使您的主要脚本(即用户使用的脚本)连接到它(是的-通过套接字...),并从中获取数据。
如果您这样做,并且想避免Web Sockets的麻烦,请尝试新的HTML5 EventStream API,因为它为您提供了最佳的解决方案:像注释一样的基础设施,而不需要长轮询的hackyness或专用Web Sockets服务器。

看起来这是正确的方法,虽然创建守护进程并不是我以前做过的事情。我找到了这里这里的教程,如果你知道更好的资源,请让我知道。此外,在var source = new EventSource('stream.php');中,守护进程stream.php应该如何工作,还不是很清楚,如果有更多的见解,也将不胜感激。 - Matt Phillips
你可能想为守护进程和事件流的其他问题开启额外的提问。随意链接它们,以便我们可以查看。感谢您的悬赏! - Mbrevda

2
如果需要保持连接,您需要保持PHP脚本的开启。通常情况下,PHP仅在调用后运行脚本并关闭(CGI,CLI),或者是混合模式(Apache中的mod_php,FCGI),其中有时PHP解释器在脚本完成后仍然保留在内存中(因此与该进程相关的所有内容都将作为套接字句柄保留)。
然而,这种方式并不安全。相反,您需要将PHP变成一个守护程序,可以将您的PHP脚本保存在内存中。一个现有的解决方案是Appserver-In-PHP。它将使您的代码一直保存在内存中,直到重启服务器。就像代码一样,您也可以在请求之间保留变量,例如连接句柄。

总的来说,我同意这个观点,根据我的经验,长时间运行的PHP脚本会有不同的结果。在许多情况下,由于PHP是以建立/拆除方法为基础设计的,因此内存泄漏很难克服。尽管如此,我已经看到并听说过成功运行长时间的PHP脚本,但你的情况可能会有所不同,但这是最好的方法。如果PHP存在内存泄漏问题,那么考虑Java或C是时候了。 - quickshiftin
如果PHP泄漏内存,请检查您的代码中是否有任何缺陷。同样地,您也可以在C或Java中编写会泄漏内存的代码。只是提醒一下。 - hakre

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