Telnet 套接字网关到 Coldfusion 事件网关以连接到 Asterisk AMI
Telnet socket gateway to Coldfusion Event Gateway to Connect to Asterisk AMI
我希望我的 ColdFusion 应用能够记录通过 Management API 从 Asterisk 主机通过 telnet 传输的事件。 ColdFusion 事件网关可以侦听特定端口但不能自己发起连接,所以我需要一个网关可以发起到 Asterisk 主机(在指定端口上)的 telnet 连接并将流式事件推送到 ColdFusion 服务器(在指定端口)。我真的不想重新发明轮子,所以有没有可以做到这一点的实用程序?
我的术语可能不正确,因为我不是那么专业,但我希望我已经充分解释了要求! 'utility' 可以驻留在 Linux 或 windows 平台上。
编辑:
要连接到 Asterisk 主机 telnet 流并由其进行身份验证,必须发送以下内容:
Action: login<CRLF>
Username: usr<CRLF>
Secret: abc123<CRLF>
<CRLF>
我知道之前发布了一个与此类似的问题(但没有回答),但我很高兴在 ColdFusion 之外找到解决方案
谢谢
使用 Coldfusion 的套接字网关。它是内置的,是 Coldfusion 中 事实上的 功能,可以使用 TCP/IP-based 协议(例如 Telnet,
)发送和响应消息
我开始怀疑我是否理解你的要求。您希望您的申请 "initiate a connection to listen to"。 CF 套接字网关可能不会 "initiate" 连接,但它会 "have a connection to listen to"。为什么要启动你已经拥有的东西?为什么 "initiate" 这个词这么重要?
无论如何,我将您的要求 "initiate a telnet connection to a host using a particular port" 解释为 "connect to a socket on another server"。为此,您不需要一整套 gateway/redirector 机器。您可以在 Coldfusion 套接字网关的 CFC 中执行此操作。它只需要 2 或 3 行代码(在网上搜索 'reading from and writing to a socket')。
因此在您的最终设计中,您将在两个套接字之间建立连接。一个在您的 Coldfusion 服务器上,另一个在主机服务器上。连接中的通信是双向的。然后,任意数量的客户端(比如 10 000 个)都可以在 CF 套接字上侦听来自主机服务器的所有消息。
如果您需要做的只是从 Asterisk 服务器捕获事件,我建议采用不同的方法。
由于您似乎在使用 Asterisk AMI,请看一下 Asterisk-Java。据我所知,它是一个 java 库,可以为您处理低级套接字通信和解析,并提供与 Asterisk 服务器交互的高级接口。因此它能够启动连接、捕获事件等等。
理论上,您可以打开连接并注册以在应用程序启动时接收事件。只要连接保持打开状态,应用程序就会从 Asterisk 接收事件。当应用程序结束时,只需关闭连接即可停止事件。
初始化连接
要简单地捕获事件,首先要创建到 Asterisk 服务器的连接。只需提供正确的主机和凭据:
managerFactory = createObject("java", "org.asteriskjava.manager.ManagerConnectionFactory");
connection = managerFactory.init( hostNameOrIP
, portNum
, userName
, theSecret ).createManagerConnection();
正在注册活动
为了接收事件,你必须先注册一个ManagerEventListener with the connection. Normally that would require writing a custom java class that implements the proper interface. However, with a bit of dynamic proxy magic,你可以使用一个标准的CFC来代替。来自 Asterisk 的任何事件都将直接路由到 CFC,并可以使用 CF 代码进行处理。
要添加侦听器,请使用名为 onManagerEvent 的单个函数创建一个 CFC。只要 Asterisk 服务器上发生注册事件,就会调用此函数。
// YourCFCListener.cfc
component {
public void function onManagerEvent(any managerEvent)
{
// For demo purposes, just output a summary of the event to a log file
WriteLog( text=arguments.managerEvent.toString(), file="AsteriskListenerLog" );
}
}
接下来创建代理并将其注册到连接中。
proxyListener = createDynamicProxy("path.YourCFCListener"
, [ "org.asteriskjava.manager.ManagerEventListener"] );
connection.addEventListener( proxyListener );
接收事件:
要开始接收事件,请登录并连接到服务器。使用掩码指定要接收的事件:"off"
、"on"
或以逗号分隔的特定事件列表(即 "system,call,log"
)。
// receive ALL events
connection.login("on");
连接打开后,您将看到事件写入演示日志文件(假设有服务器 activity)。对于一次性测试,让页面 sleep()
持续几秒钟以允许一些事件流动。然后关闭连接并停止事件:
sleep(4000);
connection.logoff()
在实际的应用程序中,您可能会打开一次连接并将其存储在持久范围内,例如 application.然后仅在应用程序关闭时关闭它。
看看 API,您可以用它做很多事情。但是,上面应该提供了一个基本的 POC 示例,让您开始捕获事件。
我以通常的方式创建了 Coldfusion 套接字网关的实例。参见,例如,https://www.bennadel.com/blog/2173-using-socket-gateways-to-communicate-between-coldfusion-and-node-js.htm.
我进行了以下设置:
1) 监听器 CFC (SocketGatewayListener.cfc) 的内容:
<cfcomponent>
<cffunction name="onIncomingMessage" returntype="struct" output="false">
<cfargument name="cfevent" >
<cfset var msg = {} >
<cfscript>
/* The code within this cfscript represents the proof of concept. 'xxx.xxx.xxx.xxx' is an IP, 1226 an arbitrary port, so the next line connects to an external socket. Make sure it is listening. */
var socket = createobject("java","java.net.Socket").init('xxx.xxx.xxx.xxx',1226);
var out = createobject("java","java.io.PrintWriter").init(socket.getOutputStream(), true);
var bufferedWriter = createobject("java","java.io.BufferedWriter").init(out);
/*Send data to external socket */
bufferedWriter.write("Authentication data at #now()#");
bufferedWriter.flush();
</cfscript>
<cfset msg["message"] = cfevent.data.message>
<cfreturn msg>
</cffunction>
</cfcomponent>
2) 配置文件内容(socketGateway.cfg):
# The port the socket server listens on.
port=9093
3) 我的系统:
冷聚变 2016
Windows 7 终极
网猫:
您可以使用可执行文件 nc.exe 来收听或向套接字网关发送消息。网关为 运行 后,使用 DOS 命令收听
nc 127.0.0.1 9093
使用类似
的命令发送消息
echo 'my test message' | nc 127.0.0.1 9093
大力士 (http://www.hw-group.com/products/hercules/index_en.html):
您可以使用 Hercules GUI 实用程序进行测试。使用它的 'TCP Client' 向你的套接字网关发送消息,它的 'TCP Server' 模拟一个套接字从不同的主机监听你的网关(代码中的 IP 和端口:xxx.xxx.xxx.xxx, 1226).
不幸的是,正如您所期望的那样,Adobe Coldfusion 的套接字网关无法广播到所有正在侦听的套接字。您只能让它回复消息的发件人。显然,这是设计使然。这是令人惊讶的。默认情况下,您会期望所有侦听套接字都收到一条消息。我将向 Coldfusion 团队提出功能请求。
我在网上找到了这两个解决方案,它们似乎提供了广播到所有功能以及更多功能:
https://github.com/nmische/cf-websocket-gateway/tree/java-websocket
https://github.com/softwarezman/cf-socketiogateway
然而,当我在 Coldfusion 2016 上测试它们时,我 运行 遇到了很多错误。在接下来的几天里,我将向 SocketGateway Java 代码添加广播到所有功能随 Coldfusion 一起提供。
我希望我的 ColdFusion 应用能够记录通过 Management API 从 Asterisk 主机通过 telnet 传输的事件。 ColdFusion 事件网关可以侦听特定端口但不能自己发起连接,所以我需要一个网关可以发起到 Asterisk 主机(在指定端口上)的 telnet 连接并将流式事件推送到 ColdFusion 服务器(在指定端口)。我真的不想重新发明轮子,所以有没有可以做到这一点的实用程序?
我的术语可能不正确,因为我不是那么专业,但我希望我已经充分解释了要求! 'utility' 可以驻留在 Linux 或 windows 平台上。
编辑: 要连接到 Asterisk 主机 telnet 流并由其进行身份验证,必须发送以下内容:
Action: login<CRLF>
Username: usr<CRLF>
Secret: abc123<CRLF>
<CRLF>
我知道之前发布了一个与此类似的问题(但没有回答),但我很高兴在 ColdFusion 之外找到解决方案
谢谢
使用 Coldfusion 的套接字网关。它是内置的,是 Coldfusion 中 事实上的 功能,可以使用 TCP/IP-based 协议(例如 Telnet,
)发送和响应消息我开始怀疑我是否理解你的要求。您希望您的申请 "initiate a connection to listen to"。 CF 套接字网关可能不会 "initiate" 连接,但它会 "have a connection to listen to"。为什么要启动你已经拥有的东西?为什么 "initiate" 这个词这么重要?
无论如何,我将您的要求 "initiate a telnet connection to a host using a particular port" 解释为 "connect to a socket on another server"。为此,您不需要一整套 gateway/redirector 机器。您可以在 Coldfusion 套接字网关的 CFC 中执行此操作。它只需要 2 或 3 行代码(在网上搜索 'reading from and writing to a socket')。
因此在您的最终设计中,您将在两个套接字之间建立连接。一个在您的 Coldfusion 服务器上,另一个在主机服务器上。连接中的通信是双向的。然后,任意数量的客户端(比如 10 000 个)都可以在 CF 套接字上侦听来自主机服务器的所有消息。
如果您需要做的只是从 Asterisk 服务器捕获事件,我建议采用不同的方法。
由于您似乎在使用 Asterisk AMI,请看一下 Asterisk-Java。据我所知,它是一个 java 库,可以为您处理低级套接字通信和解析,并提供与 Asterisk 服务器交互的高级接口。因此它能够启动连接、捕获事件等等。
理论上,您可以打开连接并注册以在应用程序启动时接收事件。只要连接保持打开状态,应用程序就会从 Asterisk 接收事件。当应用程序结束时,只需关闭连接即可停止事件。
初始化连接
要简单地捕获事件,首先要创建到 Asterisk 服务器的连接。只需提供正确的主机和凭据:
managerFactory = createObject("java", "org.asteriskjava.manager.ManagerConnectionFactory");
connection = managerFactory.init( hostNameOrIP
, portNum
, userName
, theSecret ).createManagerConnection();
正在注册活动
为了接收事件,你必须先注册一个ManagerEventListener with the connection. Normally that would require writing a custom java class that implements the proper interface. However, with a bit of dynamic proxy magic,你可以使用一个标准的CFC来代替。来自 Asterisk 的任何事件都将直接路由到 CFC,并可以使用 CF 代码进行处理。
要添加侦听器,请使用名为 onManagerEvent 的单个函数创建一个 CFC。只要 Asterisk 服务器上发生注册事件,就会调用此函数。
// YourCFCListener.cfc
component {
public void function onManagerEvent(any managerEvent)
{
// For demo purposes, just output a summary of the event to a log file
WriteLog( text=arguments.managerEvent.toString(), file="AsteriskListenerLog" );
}
}
接下来创建代理并将其注册到连接中。
proxyListener = createDynamicProxy("path.YourCFCListener"
, [ "org.asteriskjava.manager.ManagerEventListener"] );
connection.addEventListener( proxyListener );
接收事件:
要开始接收事件,请登录并连接到服务器。使用掩码指定要接收的事件:"off"
、"on"
或以逗号分隔的特定事件列表(即 "system,call,log"
)。
// receive ALL events
connection.login("on");
连接打开后,您将看到事件写入演示日志文件(假设有服务器 activity)。对于一次性测试,让页面 sleep()
持续几秒钟以允许一些事件流动。然后关闭连接并停止事件:
sleep(4000);
connection.logoff()
在实际的应用程序中,您可能会打开一次连接并将其存储在持久范围内,例如 application.然后仅在应用程序关闭时关闭它。
看看 API,您可以用它做很多事情。但是,上面应该提供了一个基本的 POC 示例,让您开始捕获事件。
我以通常的方式创建了 Coldfusion 套接字网关的实例。参见,例如,https://www.bennadel.com/blog/2173-using-socket-gateways-to-communicate-between-coldfusion-and-node-js.htm.
我进行了以下设置:
1) 监听器 CFC (SocketGatewayListener.cfc) 的内容:
<cfcomponent>
<cffunction name="onIncomingMessage" returntype="struct" output="false">
<cfargument name="cfevent" >
<cfset var msg = {} >
<cfscript>
/* The code within this cfscript represents the proof of concept. 'xxx.xxx.xxx.xxx' is an IP, 1226 an arbitrary port, so the next line connects to an external socket. Make sure it is listening. */
var socket = createobject("java","java.net.Socket").init('xxx.xxx.xxx.xxx',1226);
var out = createobject("java","java.io.PrintWriter").init(socket.getOutputStream(), true);
var bufferedWriter = createobject("java","java.io.BufferedWriter").init(out);
/*Send data to external socket */
bufferedWriter.write("Authentication data at #now()#");
bufferedWriter.flush();
</cfscript>
<cfset msg["message"] = cfevent.data.message>
<cfreturn msg>
</cffunction>
</cfcomponent>
2) 配置文件内容(socketGateway.cfg):
# The port the socket server listens on.
port=9093
3) 我的系统: 冷聚变 2016 Windows 7 终极
网猫: 您可以使用可执行文件 nc.exe 来收听或向套接字网关发送消息。网关为 运行 后,使用 DOS 命令收听
nc 127.0.0.1 9093
使用类似
的命令发送消息echo 'my test message' | nc 127.0.0.1 9093
大力士 (http://www.hw-group.com/products/hercules/index_en.html): 您可以使用 Hercules GUI 实用程序进行测试。使用它的 'TCP Client' 向你的套接字网关发送消息,它的 'TCP Server' 模拟一个套接字从不同的主机监听你的网关(代码中的 IP 和端口:xxx.xxx.xxx.xxx, 1226).
不幸的是,正如您所期望的那样,Adobe Coldfusion 的套接字网关无法广播到所有正在侦听的套接字。您只能让它回复消息的发件人。显然,这是设计使然。这是令人惊讶的。默认情况下,您会期望所有侦听套接字都收到一条消息。我将向 Coldfusion 团队提出功能请求。
我在网上找到了这两个解决方案,它们似乎提供了广播到所有功能以及更多功能:
https://github.com/nmische/cf-websocket-gateway/tree/java-websocket
https://github.com/softwarezman/cf-socketiogateway
然而,当我在 Coldfusion 2016 上测试它们时,我 运行 遇到了很多错误。在接下来的几天里,我将向 SocketGateway Java 代码添加广播到所有功能随 Coldfusion 一起提供。