我正在尝试围绕模拟器编写一个包装器,该模拟器提供Web API,以便用户可以在服务器上生成模拟并收集结果。
我最初的设计是在Apache中运行一个php模拟StartSimulation.php,这将是fork&执行模拟,并将结果传递给文件。但是,你不能分叉和exec在php内部的apache模块中。此外,它在这个实现中有点混乱,因为没有进程管理孤立的模拟,因此杀死它们并计算它们是很棘手的。使用标准Web服务器似乎有点困难,因为没有存储运行进程列表(模拟)的全局状态。
模拟器是用c ++编写的,但应该尽可能少地进行修改。我更喜欢为它编写一个包装器并执行模拟器并捕获它的标准输出并使用户可以访问它。
基本上,包装器应该有一个带有3个命令的Web可访问API。
1。)start_simulation - 基本上是forks&执行模拟器的实例,将其pid记录在表中,并将其stdout传送到已知缓冲区。包装器不应允许超过16个模拟器实例在服务器上运行。如果成功,它会向用户返回模拟代码。否则,它会返回错误代码。
2。)停止模拟 - 获取(1)中返回的模拟代码,并杀死相关的过程。
3。)get_process - 获取(1)中返回的模拟代码,查找保存该进程的stdout的已知缓冲区,并将该信息返回给用户。
我应该为此编写自定义应用程序服务器吗?如果是这样,是否有一个很好的包含一些入门代码?
由于 凯尔
答案 0 :(得分:1)
我知道这是一个老问题,但希望这对某些人来说仍然有用......
在通过http请求直接从Apache调用的PHP脚本中进行进程管理(fork / exec / wait / kill / signal等)绝对不是可行的方法。正如你所说,它很快就会变得混乱:)
我建议通过http调用的PHP脚本只是一个简单服务器进程的命令代理。如果PHP是您的首选语言,您可以这样实现。
例如,您可以使用消息队列执行此操作,如下所示...
您可以创建一个相当简单的PHP服务器来创建消息队列并等待 要进入的消息。然后它可以执行启动或停止模拟器进程的工作
远程用户通过网页表单选择操作(开始,停止,获取输出)。
这导致HTTP / POST请求将表单数据发送到您的PHP脚本(我将这作为一个AJAX调用执行此操作,这样我就可以发送数据并解释结果而无需重新加载页面)
您的服务器端PHP脚本可以解释表单数据并通过消息向PHP服务器进程发送命令
让我们用一些PHP代码来说明这一点。为了简洁起见,我要保持这种微不足道的简单。
PHP脚本(网络表单目标)
这是我们解释传入表单请求并将其转换为服务器进程的消息的地方
<?php
/*
* Responses are sent as simple text strings to be interpreted by
* the client-side JavaScript handling this AJAX call. Responses
* starting with 'ERR:' are errors, responses starting with 'ACK:'
* are acknowledgements. Simply check the first few characters of
* the response in the client-side JavaScript.
*/
header('Content-Type: text/plain; charset=UTF-8);
/*
* Here we define some message types, one per command. These should correspond
* to the command string sent from the web form
*/
$command = array(
'START_SIM' => 1,
'STOP_SIM' => 2,
'GET_STATUS' => 3,
'GET_OUTOUT' => 4
);
$queue_id = 0xbeef; /* An arbitrary message queue id */
$cmd = $_REQUEST['command']; /* The command from the web form */
/* get simulator instance id to act upon, if specified */
if (isset($_REQUEST['id']))
$sim_id = $_REQUEST['id'];
else
$sim_id = ''; /* no sim id? probably a create command */
/* check the message queue exists... */
if (msg_queue_exists($queue_id) === false) {
echo 'ERR:Message queue not found!';
return;
}
/* open the message queue and pass the command on to the server... */
if (($qhandle = msg_get_queue($queue_id)) === false) {
echo 'ERR:Failed to open message queue to server';
return;
}
if (msg_send($qhandle, $command[$cmd], $sim_id) === false)
echo 'ERR:Failed to send command';
else
echo 'ACK:Command sent ok';
?>
PHP服务器(在您的网络服务器上单独运行)
这是一个同样简单的服务器......
<?php
/*
* assume the same queue id's and defines as in the
* client code above, etc..
*/
if (($qhandle = msg_get_queue($queue_id)) === false) {
/* emit failure message to log file etc.. */
...
return;
}
while (1) {
if (msg_receive($qhandle, 0, $msgtype, $message,
true, 0, $rc) === false) {
/* log error message ... */
} else {
/*
* Get the client id (in case you want to send
* a reply back to the client) and the
* message data, which is the simulation id.
*
* Remember that we use the message type to
* indicate the command being requested
*/
$client = $message['client'];
$sim_id = $message['msg'];
evaluate_command($client, $msgtype, $sim_id);
}
}
?>
显然这非常简单,没有错误检查,你需要自己编写“evaluate_command()”函数。我只是潦草地说明了这个想法(我已经把它写在了袖口上,所以它也可能充满其他错误!)