1

我正在使用 Ubuntu 12.04。

我有一个服务可以不断地向 127.255.255.255 发送数据(二进制图像),以便允许每个未来的本地服务在需要时获取该数据。

是否可以通过 php 获取 UDP 数据流量,以便在用户连接到安装在 pc 上的 Web 服务器时向用户显示?

我已经尝试在 php 中创建一个套接字并获取数据(简单的数据只是为了证明通信),如果我通过命令行运行 php 代码,它可以工作,但是如果我通过浏览器访问网页,我什么也看不到,我可以看到持续加载数据直到它停止并显示数据的网页。这意味着 php 页面可以获取数据,但只有在应用程序停止时才会显示它。

我希望当我访问该网页时,我可以看到数据流,并且只有当我更改网页时应用程序才会停止。

该应用程序似乎运行 30 秒并记住所有输出,然后将输出写入屏幕。我没有设置 30 秒,应用程序应该永远运行,因为它进入了 while(true) 循环。

这是代码:

<body style="background-color: yellow;">
    <div style="margin: auto; margin-top: 50px;">
            <div style="margin: auto; width: 200px; font-weight: bold; font-size: 20px; margin-bottom: 20px; color: darkgreen;">Real Time View</div>

            <?php
                //Create a UDP socket
                if(!($socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)))
                {
                     $errorcode = socket_last_error();
                     $errormsg = socket_strerror($errorcode);

                     die("Couldn't create socket: [$errorcode] $errormsg \n");
                }

                //echo "Socket created <br>";

                if( !socket_set_nonblock($socket) ){
                     $errorcode = socket_last_error();
                     $errormsg = socket_strerror($errorcode);

                     die("Could not nonblock socket : [$errorcode] $errormsg \n");
                }   

                // Bind the source address
                if( !socket_bind($socket, "0.0.0.0" , 9999) ){
                     $errorcode = socket_last_error();
                     $errormsg = socket_strerror($errorcode);

                     die("Could not bind socket : [$errorcode] $errormsg \n");
                }   
                //echo "Socket bind OK <br>";

                while(1){
                     //echo "Waiting for data ... <br>";

                     //Receive some data
                     //$r = socket_recvfrom($socket, $buf, 512, 0, $remote_ip, $remote_port);
                     //echo "$remote_ip : $remote_port -- " . $buf ."<br>";

                     $r = socket_read($socket, 1024);
                     echo $r; 

                     //Send back the data to the client
                     //socket_sendto($socket, "OK " . $buf , 100 , 0 , $remote_ip , $remote_port);
                }
                socket_close($socket);


            ?>
    </div>
</body>

任何想法?

4

2 回答 2

0

你可以看看flush() 函数

“刷新 PHP 的写入缓冲区以及 PHP 正在使用的任何后端(CGI、Web 服务器等)。这会尝试将当前输出一直推送到浏览器,但有一些警告。”

您可能还必须致电ob_flush; 因此,如果您将以下内容放在战略位置,它应该可以工作:

echo "something";
flush();
ob_flush();

你可以让 PHP 无限运行set_time_limit(0)。请参阅PHP 手册。所以把这一行放在你的 php 文件的顶部。

default_socket_timeout如果 60 秒后出现问题,也请检查设置。

编辑:现在在这里运行脚本 30 分钟没有问题。现在连httpd cpu都低了。(我认为是因为睡着了)

我的工作代码:

<?
  error_reporting(E_ALL);
  ini_set('display_errors', '1');
  set_time_limit(0);
  ob_start();

  function flush_buffers(){
      ob_end_flush();
      ob_flush();
      flush();
      ob_start();
  }
  echo date("d-m-Y H:i:s");

?>
<body style="background-color: yellow;">
    <div style="margin: auto; margin-top: 50px;">
            <div style="margin: auto; width: 200px; font-weight: bold; font-size: 20px; margin-bottom: 20px; color: darkgreen;">Real Time View</div>

            <?php
                //Create a UDP socket
                if(!($socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)))
                {
                     $errorcode = socket_last_error();
                     $errormsg = socket_strerror($errorcode);
                     die("Couldn't create socket: [$errorcode] $errormsg \n");
                }

                echo "Socket created <br>";
                flush_buffers();

                if( !socket_set_nonblock($socket) ){
                     $errorcode = socket_last_error();
                     $errormsg = socket_strerror($errorcode);
                     die("Could not nonblock socket : [$errorcode] $errormsg \n");
                }

                // Bind the source address
                if( !socket_bind($socket, "0.0.0.0" , 9999) ){
                     $errorcode = socket_last_error();
                     $errormsg = socket_strerror($errorcode);
                     die("Could not bind socket : [$errorcode] $errormsg \n");
                }
                echo "Socket bind OK <br>";
                flush_buffers();

                socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>1, "usec"=>100));
                socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec"=>1, "usec"=>100));

                try {
                  while(1){
                       usleep(0.5 * 1000000); // 0.5 seconds
                       if (False === ($r = socket_read($socket, 1024))) {
                          $errorcode = socket_last_error();
                          $errormsg = socket_strerror($errorcode);
                          if ($errorcode!='11') { echo "error reading : [$errorcode] $errormsg <br>\n"; }
                       }
                       echo $r;
                       if ($r!='') { echo ".<br>"; }
                       flush_buffers();
                  }
                } finally {
                  socket_close($socket);
                }


            ?>
    </div>
</body>
<?
ob_end_flush();
?>
于 2013-07-12T10:18:25.697 回答
-1

正如答案已经提到的那样,PHP 脚本的执行时间有限。在默认情况下,这将是 30 秒。在您的脚本中,有一个 while 循环来读取套接字数据。但是,这会使脚本无限运行,这不是服务器所期望的。浏览器读取数据,直到脚本被服务器杀死。

你确实需要这样做。在这种情况下,浏览器并不期待直播。您可以使用 PHP 执行此操作并将正确的标头发送到浏览器:stream/mjpg?例如。比它应该能够显示图像流。另一种可能性是使用 javascript 套接字读取数据并将其输出到浏览器元素。

于 2014-09-07T20:29:34.623 回答