session_start que ob_start funcion php http mjpeg

que - Cómo deshabilitar el almacenamiento en búfer de salida en PHP



session_start(); ob_start(); (5)

Escribí una secuencia de comandos de retransmisión simple que se conecta a una cámara web y lee desde el socket, y emite estos datos usando la función de impresión. Los datos son datos MJPG con límites ya configurados. Acabo de mostrar los datos que se leen.

El problema es que PHP parece almacenar en búfer estos datos. Cuando configuro la cámara a 1 FPS, la alimentación se congela durante 7-8 segundos, luego muestra rápidamente 8 cuadros. Si configuro la resolución a un tamaño enorme, la cámara se mueve a más o menos 1 fotograma por segundo. Supongo que está ocurriendo algo de almacenamiento en búfer (ya que los tamaños grandes llenan el búfer rápidamente, y los tamaños bajos no), y no puedo encontrar la manera de desactivar este almacenamiento en búfer. ¿Alguien sabe cómo?

Código:

ignore_user_abort(false); $boundary = "myboundary"; //Set this so PHP doesn''t timeout during a long stream set_time_limit(0); $socketConn = @fsockopen ("192.168.1.6", 1989, $errno, $errstr, 2); if (!$socketConn) exit(); stream_set_timeout($socketConn, 10); fputs ($socketConn, "GET /mjpeg HTTP/1.0/r/n/r/n"); //Setup Header Information header("Cache-Control: no-cache"); header("Cache-Control: private"); header("Pragma: no-cache"); header("Content-type: multipart/x-mixed-replace; boundary=$boundary"); @ini_set(''implicit_flush'', 1); for ($i = 0; $i < ob_get_level(); $i++) ob_end_flush(); ob_implicit_flush(1); stream_set_blocking($f2, false); //Send data to client while (connection_status() == CONNECTION_NORMAL) { $chunk = fread($socketConn, 128); print $chunk; } fclose($socketConn);


tl; versión dr

Haz dos cosas:

  1. Inhabilita el búfer de salida del espacio de usuario, ya sea ...

    • A nivel mundial, ya sea por ...

      • Desactivando output_buffering en tu php.ini, o
      • Desactivando output_buffering en tu configuración de Apache usando

        php_flag "output_buffering" Off

    • o solo por el guión que te importa, ya sea por ...

      • llamando a ob_end_flush() , o
      • llamando a ob_end_clean()
  2. Además, deshabilite el búfer de salida de nivel de servidor tanto como sea posible, ya sea por:

    • llamando a ob_implicit_flush() al comienzo de su script, o
    • invocando flush() después de cada declaración de echo u otra instrucción que agrega salida al cuerpo de respuesta

Versión más larga

Confusamente, hay dos capas de almacenamiento intermedio que pueden ser relevantes y la documentación de PHP hace un trabajo pobre de distinguir entre los dos.

El buffer de salida

La primera capa suele ser referida por los documentos PHP como el ''buffer de salida''. Esta capa de almacenamiento en búfer solo afecta la salida al cuerpo de la respuesta HTTP, no a los encabezados. Puede activar el almacenamiento en búfer de salida con ob_start() y desactivarlo con ob_end_flush() o ob_end_clean() . También puede hacer que todos los scripts comiencen automáticamente con el búfer de salida utilizando la opción output_buffering en php.ini.

El valor predeterminado de esta opción para las versiones de producción de php.ini es 4096, lo que significa que los primeros 4096 bytes de salida se almacenarán en el búfer de salida, en ese punto se vacían y el búfer de salida se desactiva.

Puede desactivar esta capa de almacenamiento en búfer de forma global estableciendo output_buffering en Off en su archivo php.ini (o usando

php_flag "output_buffering" Off

en tu configuración de Apache, si estás usando Apache). Alternativamente, puede desactivarlo para un solo script llamando a ob_end_clean() o ob_end_flush() al comienzo del script.

El búfer de escritura y el búfer del servidor web

Más allá del búfer de salida, el manual de PHP se refiere al "búfer de escritura", más cualquier sistema de búfer que tenga su servidor web. Si está utilizando PHP con Apache a través de mod_php , y no está usando mod_gzip , puede llamar a flush() para vaciarlos; con otros backends, podría funcionar también, aunque el manual es cauteloso para dar garantías:

Descripción

void flush ( void )

Vacía los búferes de escritura de PHP y cualquier backend que PHP esté usando (CGI, un servidor web, etc.). Esto intenta llevar la salida actual al navegador con algunas advertencias.

flush () puede no ser capaz de anular el esquema de almacenamiento en búfer de su servidor web y no tiene ningún efecto sobre el almacenamiento en búfer del lado del cliente en el navegador. Tampoco afecta el mecanismo de búfer de salida del espacio de usuario de PHP. Esto significa que tendrá que llamar tanto a ob_flush() como a flush () para purgar los búferes de salida ob si los está utilizando.

También hay un par de maneras en que puede hacer que PHP llame automáticamente a flush() cada vez que haga echo algo (o haga cualquier otra cosa que emita eco en el cuerpo de la respuesta).

El primero es llamar a ob_implicit_flush() . Tenga en cuenta que esta función es engañosamente nombrada; dado su prefijo ob_ , cualquier persona razonable esperaría que afectaría al ''buffer de salida'', como hacen ob_start , ob_flush , etc. Sin embargo, este no es el caso; ob_implicit_flush() , como flush() , afecta al búfer de salida del nivel del servidor y no interactúa de ninguna manera con el búfer de salida controlado por las otras funciones ob_ .

El segundo es habilitar globalmente el enjuague implícito configurando el indicador implicit_flush en On en su php.ini. Esto es equivalente a invocar ob_implicit_flush() al inicio de cada script. Tenga en cuenta que el manual desaconseja esto, citando crípticamente "implicaciones graves de rendimiento" , algunas de las cuales exploro en esta respuesta tangencialmente relacionada .


El almacenamiento en búfer de salida se puede aplicar en capas y he tenido casos en los que el código anterior había alcanzado varios niveles. Esto los limpiará a todos.

while (ob_get_level()) ob_end_clean(); // or ob_end_flush() if you want the contents of the buffer.


En lugar de deshabilitar el almacenamiento en búfer de salida, puede simplemente llamar a flush() después de cada operación de lectura. Esto evita tener que meterse con la configuración del servidor y hace que su script sea más portátil.


Podemos dar el siguiente código en el archivo .htaccess para deshabilitar el almacenamiento en búfer de salida en PHP

php_flag "output_buffering" off


Sé que esta pregunta es un poco antigua, pero volviendo a esta pregunta, puede desactivar el almacenamiento en búfer de salida en un script a script, como este:

if (ob_get_level()) ob_end_clean();

Esto debería desactivar todos los búferes de salida para cualquier script que lo siga.