2009-09-16 15 views

Respuesta

18

Sí, eso es para lo que socket_set_nonblock() es. El código de interacción del socket deberá escribirse de manera diferente, teniendo en cuenta los significados especiales que los códigos de error 11, EWOULDBLOCK y 115, EINPROGRESS, asumen.

He aquí algunos ejemplos de código novelada tanto, desde un bucle de toma de votación PHP sincronización, conforme a lo solicitado:

$buf = ''; 
$done = false; 
do { 
    $chunk = socket_read($sock, 4096); 
    if($chunk === false) { 
     $error = socket_last_error($sock); 
     if($error != 11 && $error != 115) { 
      my_error_handler(socket_strerror($error), $error); 
      $done = true; 
     } 
     break; 
    } elseif($chunk == '') { 
     $done = true; 
     break; 
    } else { 
     $buf .= $chunk; 
    } 
} while(true); 
+0

¿Qué quiere decir con diferente? ¿Puede mostrarme algún ejemplo de código de eventos recibidos de datos asincrónicos? –

+0

Entonces, ¿esto es sincrónico, pero no bloquea? Entonces, ¿qué significa exactamente no bloquear? –

+3

No, es asincrónico y basado en encuestas. El código es de un mecanismo de votación más grande. PHP no tiene soporte para eventos de E/S de socket controlados por señal/interrupción como lo que está pidiendo, hasta donde yo sé. Se logran comunicaciones asíncronas mediante el uso de operaciones que no esperan la finalización pero que vuelven inmediatamente, con un código de error indicativo, si la operación no está lista. Como lee en un socket sin bloqueo. Hay muchos tutoriales sobre el uso de socket asíncrono en C que entrarán en muchos detalles sobre esto; El soporte de PHP es solo una capa sobre el material C estándar. – chaos

0

yo sepa PHP está estrictamente singlethreaded, lo que significa que no puede hacer esto de forma asíncrona, ya que la ejecución de secuencias de comandos es siempre lineal.

Ha pasado un tiempo desde que hice esto, pero por lo que recuerdo, solo puede abrir el socket y hacer que el script continúe la ejecución al recibir los datos.

+0

Incluso la muestra del código del caos parece corroborar este hecho. –

+1

PHP proporciona stream_select para operaciones de socket asíncronas, análoga a posix select(). – karunski

+1

select() es sincrónico: simplemente le permite saber si un socket está listo para leer/escribir. Todavía lo llamas desde un solo hilo, y bloqueas en la llamada select() en lugar de read() o write(). –

5

¿Cómo hago lo mismo de forma asíncrona? por lo que puede responder a los datos en un evento de datos recibida, en lugar de votación para datos, etc.

Tendrá que ejecutar la secuencia de comandos y emitir stream_select para comprobar weither hay algún dato a recibir. Procese y envíe datos de vuelta.

5

El término "asíncrono" a menudo se utiliza incorrectamente en la programación de la red. Para E/S, asincrónico a menudo solo se usa como otra palabra para no bloquear. Esto significa que el proceso puede continuar antes de que una llamada en la API de la red haya completado la transmisión.

Para la ejecución del proceso en general, asíncrona significa que múltiples instrucciones son capaces de ser computado al mismo tiempo (simultáneamente).

En otras palabras, asíncrono de E/S no es verdaderamente asíncrono a menos que múltiples hilos se utilizan para permitir múltiples lee/escribe/acepta que ocurra simultáneamente - todos los sockets tendrán que esperar en una llamada síncrona sin bloqueo si tiene datos para leer/escribir o no bloquearán, y leer/escribir un archivo grande puede tomar segundos o incluso minutos si no se interrumpe. Tenga en cuenta que esto requeriría un flujo perfecto entre el cliente y el servidor o el propio TCP interrumpirá la transmisión. Por ejemplo, un servidor que envía más rápido que un cliente puede descargar causaría un bloqueo en una escritura.

Por lo tanto, desde un punto de vista estricto, PHP no puede realizar una red asíncrona, solo que no bloquea. En resumen, la progresión del proceso se detendrá mientras la llamada de red pueda leer/escribir de manera útil, etc. Sin embargo, el proceso continuará cuando la llamada no pueda leer/escribir de manera útil o bloquearía de otro modo. En un sistema verdaderamente asíncrono, el proceso continuará independientemente, y la lectura/escritura se realizará en un hilo diferente. Tenga en cuenta que el bloqueo de E/S todavía se puede hacer de forma asíncrona si se realiza en un hilo diferente.

Además, PHP no puede realizar E/S controladas por eventos sin instalar una extensión que lo admita. De lo contrario, deberá realizar alguna forma de sondeo para realizar E/S sin bloqueo en PHP. El código de Chaos sería un ejemplo de lectura funcional sin bloqueo si usaba socket_select.

Dicho esto, la función de selección todavía permitirá el comportamiento verdadero sin bloqueo en PHP. En C, los servicios de votación tienen una pérdida de rendimiento sobre el evento, así que estoy seguro de que sería lo mismo para PHP. Pero esta pérdida se produce en nanosegundos-microsegundos, dependiendo de la cantidad de sockets, donde el tiempo ahorrado a partir de una llamada sin bloqueo suele ser de milisegundos, o incluso segundos, si la llamada espera.

Cuestiones relacionadas