PHP 套接字、与服务器的永久连接以接收来自 Asterisk AMI 的事件?
我正在编写一个 PHP 脚本来充当迷你“守护进程”来从远程套接字接收数据。远程服务器是一个 Asterisk VoIP 服务器,我将连接到 Asterisk 管理界面 (AMI) 以尝试接收 AMI 事件通知。连接将通过始终在线的 SSH 隧道(使用 autossh)进行,到目前为止,该隧道对于我们的使用来说已经足够稳定。
计划如下...
- 连接到 SSH 隧道本地端口的 PHP 脚本,该脚本使用
fsockopen()
或最有可能的pfsockopen()
转发到另一端的远程端口code> - PHP 脚本将从 CLI 运行,我想我应该在 cron 作业上有某种 shell 脚本来检查 PHP 脚本是否因任何原因而停止,
- 我需要这个 PHP 脚本永久运行,并永久连接到套接字接收数据每当另一端发布它时
- 内存和CPU都不是问题,因为我们的内联网服务器上有大量资源(严重使用不足),但同样我不希望这个脚本失控
- PHP脚本有望对偶尔发生的情况做出反应数据出现在套接字的另一端,有时会在 MySQL 数据库中插入或更新数据。显然,我会在必要时打开/关闭 MySQL 连接,而不仅仅是让它挂起。
首先,这是一个永远行不通的可怕想法吗?
我意识到 PHP 可能不是像这样的小型守护进程的最佳语言,但我之前在 CLI 上使用 PHP 取得了成功,而且这是我最近最熟悉的语言。
当数据在套接字的另一端发布时,是否有任何 PHP 函数可以立即生效?
或者我会像这样使用 fread()
循环...
while (!feof($socket)) {
$output .= fread($socket, 8192);
}
循环选项似乎有点混乱,所以我只是想知道是否有另一种方法可以使脚本保持连接到套接字但在一些数据出现之前基本上处于闲置状态。
当考虑将永久运行的 PHP 脚本连接到套接字时,我应该注意哪些缺点/陷阱?
干杯,B
I'm looking to write a PHP script to act as a mini "daemon" to receive data from a remote socket. The remote server is an Asterisk VoIP server and I'll be connecting to the Asterisk Management Interface (AMI) in an attempt to receive AMI Event notifications. The connection will be through an always-on SSH tunnel (using autossh) which has been stable enough for our use so far.
Here's the plan...
- A PHP script connecting to the local port of the SSH tunnel which forwards to the remote port at the other end using
fsockopen()
or most likelypfsockopen()
- The PHP script will be run from CLI and I guess I should have some sort of shell script on a cron job to check that the PHP script hasn't stopped for any reason
- I'll need this PHP script to be running permanently, and permanently connected to the socket to receive data whenever it's published by the other end
- Memory and CPU is not a problem as we have plenty of resources on our intranet server (criminally under used) but equally I don't want this script spiralling out of control
- The PHP script will hopefully react to occasional data appearing at the other end of the socket and sometimes inserting or updating data in a MySQL database. Obviously I'll open/close the MySQL connection when necessary, not just leave it hanging.
First of all, is this a terrible idea that will never work?
I realise PHP's probably not the best language for a sort of small daemon like this but I've had success with PHP on CLI before and it's the language I'm most comfortable with these days.
Are there any PHP functions that can spring into action when data is published at the other end of the socket?
Or would I just loop using fread()
like this...
while (!feof($socket)) {
$output .= fread($socket, 8192);
}
The loop option seems a bit of a mess so I'm just wondering if there's another way that will mean the script stays connected to the socket but basically idle until some data appears.
What cons/pitfalls should I be aware of when thinking about having a permanently running PHP script connected to a socket?
Cheers, B
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在编写 PHP 守护程序时,您应该注意内存消耗。
如果不小心 unset()/free()d,您的守护进程可能会随着时间的推移消耗越来越多的内存。
正如您已经说过的,PHP 不是最好的语言,但它肯定会起作用。我已经做过几次这样的“hack”。
请注意,TCP 套接字上的 fread() 是非阻塞的。由于每一行都以 CR/LF 终止 (\r\n),并且两个 CR/LF 标记 AMI 事件/命令的结束,因此您可能需要读取直到出现“\r\n\r\n”,然后处理此行事件,然后再次开始阅读。我将设置套接字阻塞并使用 fgets() 而不是 fread()。这样就更容易检测 AMI 事件的结束 - 无需进行字符串魔术/分割。
you should be aware of memory consumption when writing a PHP daemon.
If not carefully unset()/free()d, your daemon may eat more and more memory over time.
as you already said, PHP is not the best language for this, but it will definitely work. i already did that "hack" a few times.
be aware that fread() on a TCP socket will be non-blocking. As each line is CR/LF terminated (\r\n) and two CR/LF mark the end of an AMI event/command, you may want to read until "\r\n\r\n" occurs, then process this event and then begin reading again. i'd set the socket blocking and use fgets() instead of fread(). that way its much easier to detect the end of an AMI event - without needing to do string magic / splitting.
看看 ZeroMQ,异步消息库。
http://en.wikipedia.org/wiki/ZeroMQ
这是 php 绑定的链接:
http://www.zeromq.org/bindings:php
Have a look at ZeroMQ, asynchronous message library.
http://en.wikipedia.org/wiki/ZeroMQ
Here's the link to the php bindings:
http://www.zeromq.org/bindings:php