简介
Server-Sent Events (SSE) 是一种 HTML5 技术,它使 Web 应用程序可以从服务器端接收自动更新,而无需进行轮询或其他技术。与 WebSockets 不同,SSE 是 HTTP 1.1 的一部分,因此它没有套接字。SSE 相对于 WebSockets 的优点是它可以由现代 Web 服务器(如 Nginx 和 Apache)直接支持,因此无需使用专用服务器。
在本文中,我们将介绍如何使用 SSE 实现远程代码执行,这对于实时应用程序和故障排除很有用。
初步实现
首先,让我们介绍一个简单的 SSE 实现,该实现接收服务器发送的随机数,然后将该数字显示在网页上。在使用 SSE 之前,必须将服务器响应标记为“text/event-stream”。
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <title>SSE Demo</title> </head> <body> <h1>SSE Demo</h1> <p>Random Number:</p> <div id="result"></div> <script> var evtSource = new EventSource("randnum.php"); evtSource.onmessage = function(event) { document.getElementById("result").innerHTML = event.data; }; </script> </body> </html>
randnum.php 的代码如下:
// javascriptcn.com 代码示例 <?php header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); while(true) { $rand_num = rand(1, 100); echo "data: $rand_num\n\n"; ob_flush(); flush(); sleep(1); } ?>
这段代码中的 while 循环将不断生成随机数,并将其作为文本流发送到客户端。客户端的 SSE 事件监听器将在每次接收到数据时更新页面上的数字。
远程代码执行
现在让我们稍微扩展这个实现,以实现远程代码执行的功能。在这里,我们将通过 SSE 接收用户在网页上输入的代码,然后将其发送到服务器,服务器将运行该代码并将结果返回给客户端。
HTML 代码:
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <title>SSE Remote Code Execution Demo</title> </head> <body> <h1>SSE Remote Code Execution Demo</h1> <p>Enter some code:</p> <textarea id="code"></textarea> <button onclick="runCode()">Run</button> <p>Output:</p> <div id="output"></div> <script> var evtSource = new EventSource("exec.php"); evtSource.onmessage = function(event) { document.getElementById("output").innerHTML = event.data; }; function runCode() { var code = document.getElementById("code").value; evtSource.dispatchEvent(new CustomEvent("cmd", {detail: code})); } </script> </body> </html>
exec.php 的代码如下:
// javascriptcn.com 代码示例 <?php header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); while(true) { $event = ""; if(!empty($_SERVER["HTTP_LAST_EVENT_ID"])) { $event = "id: ".$_SERVER["HTTP_LAST_EVENT_ID"]."\n\n"; } echo $event; ob_flush(); flush(); sleep(1); if(isset($_GET['retry'])) { echo "retry: ".$_GET['retry']."\n\n"; ob_flush(); flush(); } if(isset($code)) { $output = eval($code); echo "data: $output\n\n"; ob_flush(); flush(); unset($code); } } function _log($msg) { if(!isset($_SERVER["HTTP_LAST_EVENT_ID"])) { echo "id: ".md5($msg)."\n"; } echo "data: $msg\n\n"; ob_flush(); flush(); } ?>
在 PHP 代码中,我们使用 while 循环实现 SSE 服务器并等待接收来自客户端的 cmd 事件。一旦我们收到了该事件,我们将其包含的代码合并为一个变量 $code,并运行它。最后,我们将计算结果发送回客户端。
当执行代码时,我们需要使用 eval() 函数。因此要非常小心,保证与用户的输入一起使用 eval() 时代码中不包含任何不受信任的内容。
在客户端代码中,我们添加了 runCode() 函数,该函数获取 textarea 元素中的代码,创建一个自定义事件 cmd 并将代码信息传递给服务器。
总结
Server-Sent Events 是一种非常有用的技术,可以在 Web 应用程序中实现实时更新和远程代码执行等功能。使用 SSE,我们可以避免使用传统轮询技术来监控服务器端数据,并减少了 WebSockets 中处理套接字的复杂性。在编写使用 SSE 的应用程序时,我们应该记住,SSE 事件发送到客户端,不保证原子性。因此,我们必须分析事件数据并正确处理每个事件。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6545275d7d4982a6ebeef141